我正在使用Java线程,我编写了这个创建多个线程并运行它们的小程序。在每个线程中,值会多次递增。我使用了ThreadLocal类,因此没有争用资源。
来源:
class MyValueHolder {
public static ThreadLocal<Integer> value = new ThreadLocal<Integer>()
{
protected Integer initialValue() {
return 0;
}
};
public static void increment() {
value.set(value.get() + 1);
}
public static Integer get() {
return value.get();
}
}
class MyTask implements Runnable {
public static int counter;
public MyTask() {
counter++;
}
public void run() {
for(int i = 0; i < 100; i++) {
MyValueHolder.increment();
}
System.out.println("MyTask " + counter + ", Value " + MyValueHolder.get());
}
}
public class Main {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
for(int i = 0; i < 5; i++) {
es.execute(new MyTask());
}
es.shutdownNow();
}
}
完成后输出大部分时间是这样的:
MyTask 5, Value 100
MyTask 5, Value 100
MyTask 5, Value 100
MyTask 5, Value 100
MyTask 5, Value 100
这是我期望看到的。
然而,有时我得到这样的东西:
MyTask 2, Value 100
MyTask 4, Value 200
MyTask 5, Value 300
MyTask 5, Value 100
MyTask 5, Value 100
现在这令人困惑。即使每个任务完全相同,为什么值会有所不同?
答案 0 :(得分:5)
如果Runnable
完成,则在添加所有Runnable
之前,CachedThreadPoolExecutor会重用线程。如果发生这种情况,该线程的ThreadLocal
也将被重用。
答案 1 :(得分:1)
如上所述,ThreadLocal正在重复使用。
对于计数器,请改用AtomicInteger并设置初始值。 counter ++不是一个原子操作,它的两个操作并不是线程安全的。
答案 2 :(得分:0)
线程会在你得到输出时继续运行你应该等待它们完成你可以尝试isAlive();与线程