我想知道我们什么时候需要使用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);
}
}
我的问题是,我是否需要将lineCnt
方法中的readNWrite()
设为threadlocal?
答案 0 :(得分:2)
lineCnt
已经是“线程本地”,因为它在堆栈上。仅在需要实例成员变量的线程局部副本时才使用ThreadLocal
。
答案 1 :(得分:2)
不,你不需要在这里使用ThreadLocal - 你的代码看起来非常好:
lineCnt
是一个局部变量,因此不会在thread =&gt;中共享它是线程安全的counter.getAndAdd(lineCnt);
是原子和线程安全的操作如果您有兴趣,有关于ThreadLocal使用的SO有几篇帖子,例如this one。
答案 2 :(得分:1)
您不需要明确地将lineCnt设为ThreadLocal
。 lineCnt
是线程的局部变量。任何其他线程都无法访问它。
您可以获得有关ThreadLocal here
的更多信息来自javadoc
的ThreadLocal这些变量与正常对应物的不同之处在于每个变量 访问一个(通过其get或set方法)的线程有自己的, 独立初始化变量的副本。 ThreadLocal实例 通常是希望关联的类中的私有静态字段 状态与线程
答案 3 :(得分:1)
- Thread
有Stack
,Register
和Program Counter
。
- lineCnt
已进入ThreadLocal
。
- lineCnt
是此主题的实例变量lineCnt 的个人副本,其不可见到任何其他线程。