多个线程和AtomicInteger

Chr*_*urn 2 java multithreading atomicinteger java-threads

我从原子学教程中获取了这段代码,它说:

"通过使用AtomicInteger作为Integer的替代,我们能够在线程安全的庄园中同时增加数量,而无需同步对变量的访问.方法incrementAndGet()是一个原子操作,所以我们可以安全地从多个调用此方法线程".

它说这将返回正确的结果,但是实例都没有达到1000,它们通常相当少,例如

test1 result = 532
test2 result = 128
Run Code Online (Sandbox Code Playgroud)

怎么了 ?

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();           
    }    
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*ael 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
}
Run Code Online (Sandbox Code Playgroud)

如果在打印值之前明确等待执行程序服务完成,您应该看到预期的结果:

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!
    }
}
Run Code Online (Sandbox Code Playgroud)