public static void main(String[] args) {
AtomicInteger integer = new AtomicInteger(0);
ThreadPoolExecutor executor = new ThreadPoolExecutor(4, 4, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100));
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
list.stream()
.map(i -> CompletableFuture.runAsync(() -> {
integer.updateAndGet(a -> {
System.out.println("当前数字:" + i);
return a + i;
});
}
, executor))
.collect(Collectors.toList())
.forEach(CompletableFuture::join);
System.out.println(integer.get());
executor.shutdown(); // 关闭线程池
}
运行结果如下:
当前数字:2
当前数字:5
当前数字:6
当前数字:7
当前数字:8
当前数字:9
当前数字:10
当前数字:1
当前数字:3
当前数字:4
当前数字:1
当前数字:3
当前数字:3
当前数字:4
当前数字:4
55
可以看得出来,有一些方法重复打印了,说明integer.updateAndGet()这个方法被重复调用了。如果说integer.updateAndGet()这个方法传入的是一个外部方法,比如数据库入库操作并返回行数,就会出现线程不安全问题了,数据会重复插入。这是因为这个方法在多线程环境下,尝试更新值失败时,方法会被重新调用,导致重复执行。因此传入的外部方法不能对外部结果产生副作用,比如入库操作之类。