1

我想知道我们什么时候需要使用 threadlocal 变量?,我有一个运行多个线程的代码,每个线程都读取 S3 上的一些文件,我希望跟踪总共从文件中读取了多少行,这是我的代码:

final AtomicInteger logLineCounter = new AtomicInteger(0); 
for(File f : files) {
   calls.add(_exec.submit(new Callable<Void>() {
    @Override
    public Void call() throws Exception {
       readNWrite(f, logLineCounter);
       return null;
    }
    }));
}
for (Future<Void> f : calls) {
   try {
      f.get();
   } catch (Exception e) {
      //
   }
}
LOGGER.info("Total number of lines: " + logLineCounter);
...

private void readNWrite(File f, AtomicInteger counter) {
    Iterator<Activity> it = _dataReader.read(file);

    int lineCnt = 0;
    if (it != null && it.hasNext()) {
       while(it.hasNext()) {
         lineCnt++;
         // write to temp file here

       }
       counter.getAndAdd(lineCnt);
    }
}

我的问题是我是否需要将方法中的lineCntinreadNWrite()设为 threadlocal?

4

4 回答 4

2

lineCnt已经是“线程本地”,因为它在堆栈上。ThreadLocal仅在需要实例成员变量的线程本地副本时使用。

于 2013-01-03T06:13:11.850 回答
2

不,您不需要在这里使用 ThreadLocal - 您的代码看起来非常好:

  • lineCnt是一个局部变量,因此不跨线程共享 => 它是线程安全的
  • counter.getAndAdd(lineCnt);是原子和线程安全的操作

如果你有兴趣,SO上有几篇关于ThreadLocal使用的帖子,比如这篇

于 2013-01-03T06:13:20.173 回答
1

您不需要明确地使 lineCnt a ThreadLocallineCnt是线程的局部变量。任何其他线程都无法访问它。

您可以在此处获取有关 ThreadLocal 的更多信息

来自javadoc的 ThreadLocal

这些变量不同于它们的正常对应变量,因为每个访问一个(通过它的 get 或 set 方法)的线程都有它自己的、独立初始化的变量副本。ThreadLocal 实例通常是希望将状态与线程相关联的类中的私有静态字段

于 2013-01-03T06:18:20.997 回答
1

- AThreadStack, Register, 和Program Counter.

- lineCnt已经进入了ThreadLocal

- lineCnt此线程的实例变量 lineCnt的个人副本,它对任何其他线程都不可见。

于 2013-01-03T06:22:08.407 回答