我从原子学教程中获取了这段代码,它说: -
"通过使用AtomicInteger作为Integer的替代,我们能够在线程安全的庄园中同时增加数量,而无需同步对变量的访问。方法incrementAndGet()是一个原子操作,因此我们可以安全地从多个线程调用此方法。"
它说这会返回正确的结果,但是1000实例都没有达到1000,它们通常要少得多,例如
test1 result = 532
test2 result = 128
怎么了?
public class AtomicsTest {
public static void main(String... args){
AtomicsTest test = new AtomicsTest();
test.test1();
test.test2();
}
public void test1() {
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newSingleThreadExecutor();
IntStream.range(0,1000).forEach(i->executor.submit( atomicInt::incrementAndGet ));
System.out.println("test1 result = "+ atomicInt.get());
executor.shutdown();
}
public void test2() {
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0,1000).forEach(i->executor.submit( atomicInt::incrementAndGet ));
System.out.println("test2 result = " + atomicInt.get());
executor.shutdown();
}
}
答案 0 :(得分:6)
您的问题是您在提交线程后立即打印该值,尽管并非所有线程都已完成。
public void test1() {
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newSingleThreadExecutor();
IntStream.range(0,1000).forEach(i->executor.submit( atomicInt::incrementAndGet ));
// All threads submitted (not necessarily finished)
System.out.println("test1 result = "+ atomicInt.get());
executor.shutdown();
// Threads are still not necessarily done
}
如果在打印值之前明确等待执行程序服务完成,您应该会看到预期的结果:
public void test1() {
try {
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newSingleThreadExecutor();
IntStream.range(0,1000).forEach(i->executor.submit( atomicInt::incrementAndGet ));
executor.shutdown();
// Wait a maximum of ~a million billion years
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);
System.out.println("test1 result = "+ atomicInt.get());
}
catch (InterruptedException ex)
{
// Oh no!
}
}