关于ExecutorService#submit的错误

时间:2018-01-16 09:14:59

标签: java

public class CASTest {

private static final int ii = 10;
public static AtomicInteger ai = new AtomicInteger();
//public static CountDownLatch latch = new CountDownLatch(ii);

public static void main(String[] args) {
    DemoRunnable dr = new DemoRunnable();
    List<Future<AtomicInteger>> list = new ArrayList<Future<AtomicInteger>>(ii);
    ExecutorService es = Executors.newCachedThreadPool();
    for (int i = 0; i < ii; i++) {
        list.add(es.submit(new Callable<AtomicInteger>() {
            @Override
            public AtomicInteger call() throws Exception {
                try {
                    Thread.sleep(20);
                    ai.incrementAndGet();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return ai;
            }
        }));
    }
    for (int i = 0; i < list.size(); i++) {
        try {
            System.out.println(list.get(i).get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            es.shutdown();
        }
    }
}
}

和控制台打印 enter image description here

我想要这样的控制台打印&#34; 1 2 3 4 ... 10&#34;按顺序,但为什么它这样做?

1 个答案:

答案 0 :(得分:3)

没有同步,所以没有什么可以保证第5个线程会将ai从4增加到5。

使用AtomicInteger唯一可以确保的是,在10个增量之后,最终值将为10.

如果您希望打印10个不同的ai值(尽管按任意顺序排列),则应使用incrementAndGet返回的值。

List<Future<Integer>> list = new ArrayList<Future<Integer>>(ii);
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < ii; i++) {
    list.add(es.submit(new Callable<Integer>() {
        @Override
        public Integer call() throws Exception {
            int res = 0;
            try {
                Thread.sleep(20);
                res=ai.incrementAndGet();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return res;
        }
    }));
}
for (int i = 0; i < list.size(); i++) {
    try {
        System.out.println(list.get(i).get());
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } finally {
        es.shutdown();
    }
}

这将输出如下内容:

1
2
7
5
10
4
3
6
9
8

将打印所有唯一值,但顺序将是任意的。