我正在尝试Java多线程计数器。我第一次尝试在没有任何同步的情况下观察比赛情况。但我的计数器不会按工作线程递增。
代码-主要方法
public static void main(String... args) {
System.out.println("Program started");
Integer sum = 0;
System.out.println("Initial Sum : " + sum);
for (int i = 0; i < 100; i++) {
WorkerThread workerThread = new WorkerThread(sum, i);
workerThread.run();
}
System.out.println("Final Sum : " + sum);
}
代码-WorkerThread类
public class WorkerThread implements Runnable {
private Integer localSum;
public WorkerThread(Integer sum, int i){
localSum = sum;
System.out.println(localSum);
}
@Override
public void run() {
localSum += 1;
}
}
我想知道为什么递增localSum
不会影响Integer包装器对象sum
。sum
值保持为0。有人能帮我弄清楚如何将Integer包装器传递到线程中并增加原始值吗?
问题是localSum += 1
没有做你认为它会做的事情。
Integer
对象是不可变的:不能更改Integer
的值。localSum+=1
语句创建一个新的Integer
实例,并更改localSum
变量以引用新实例。同时,main()
例程的sum
变量将始终引用原始的、不可变的实例。
@Murat Karagöz说;使用AtomicInteger
"这将解决两个问题;
AtomicInteger
实例是可变的,并且ai.incrementAndGet()
操作和其他AtomicInteger
操作是线程安全的
您的程序在编写时不需要线程安全,但一旦您对其进行更改,就需要来实际创建多个线程。
如果您将所有的AtomicInteger
变量设置为final
,它将帮助您正确处理。例如。;
public class WorkerThread implements Runnable {
private final AtomicInteger localSum;
public WorkerThread(AtomicInteger sum, int i){
localSum = sum;
System.out.println(localSum.get());
}
...
}
您不希望意外地更改localSum
字段的值(即,您不希望更改它指向的AtomicInteger
实例(。您希望更改AtomicInteger
实例本身。