【问题标题】:How to initialize ThreadLocal<List<Object>>如何初始化 ThreadLocal<List<Object>>
【发布时间】:2017-02-17 08:10:59
【问题描述】:

以下是我的代码,我在其中声明了一个ThreadLocal 变量:

public static final ThreadLocal<List<Object>> ARGS = new ThreadLocal<>(); 

我在下面的 sn-p 中使用了这个变量:

private static void getParams(Token... tokens) {
    if(ARGS == null) {
        new LinkedList<>();
    }
    if(tokens.length > 2) {
        for(Token token : Arrays.copyOfRange(tokens, 2, tokens.length)) {
            ARGS.get().add(ArgHelper.resolveArg(token));
        }
    }
}

下面一行:

ARGS.get().add(ArgHelper.resolveArg(token)); 

给了我NullPointerException 你我从ArgHelper.resolveArg(token) 获得价值。

【问题讨论】:

  • new LinkedList&lt;&gt;(); 这一行毫无意义。你能发布堆栈异常吗?
  • 引起:com.weather.bigweb.steps.keywords.Exec.getParams(Exec.java:77) 处 com.weather.bigweb.steps.keywords.Exec 处的 java.lang.NullPointerException。 exec(Exec.java:53) at com.weather.bigweb.steps.helper.KeywordHelper.execKeyword(KeywordHelper.java:40) at com.weather.bigweb.steps.helper.Step.step(Step.java:53) ... 20 更多
  • 还是不相关,你怎么知道ARGS.get().add(ArgHelper.resolveArg(token));会抛出NPE

标签: java nullpointerexception thread-local


【解决方案1】:

注意:

if(ARGS == null) {
  new LinkedList<>();
}

什么都不做。 ARGS 被创建为 final 非空值,因此永远不会输入此块。即使是这样,单独调用new LinkedList&lt;&gt;(); 也只会构造一个LinkedList 实例,该实例会立即超出范围并被垃圾回收。没有什么可以引用它。

要正确初始化ThreadLocal,请查看documentation,它提供了一个示例,说明如何设置初始值(通过覆盖恰当命名的initialValue() 方法)。

你可以做类似的事情:

public static final ThreadLocal<List<Object>> ARGS = new ThreadLocal<List<Object>>() {
  @Override protected List<Object> initialValue() {
    return new LinkedList<>();
  }
};

也就是说,一些指针:

  • 在几乎所有情况下,您都应该更喜欢 ArrayList 而不是 LinkedList
  • 除非绝对必要,否则请创建ARGS private。通常最好尽量减少 ThreadLocal 实例的可见性,例如将其限制为包含类,并向该类的用户公开更好的 API。
  • 考虑一个比 List&lt;Object&gt; 更有意义的类型 - 如果它可以包含任何 Object,则强制所有用户检查和转换列表的内容。

【讨论】:

    【解决方案2】:

    Java 8

    private static final ThreadLocal<List<Object>> list = 
        ThreadLocal.withInitial(ArrayList::new);
    

    【讨论】:

      【解决方案3】:

      这不是您使用ThreadLocal 的方式。

      您可能希望以下代码初始化一个空的本地线程,而不是您损坏的代码。

      if(ARGS.get() == null) {
          ARGS.set(new LinkedList<>());
      }
      

      当然,我完全不建议使用ThreadLocal,尤其是如果您没有使用它的经验。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-08
        • 2016-08-22
        • 2015-08-04
        • 2021-08-03
        相关资源
        最近更新 更多