java8 原子类型
java8 提供的包
java.concurrent.atomic
包含了许多有用的类实现原子操作。原子操作是多个线程同时执行,确保其是安全的,且并不需要synchronized
关键字。这里介绍 AtomicInteger、AtomicBoolean, AtomicLong 和 AtomicReference,这里主要演示AtomicInteger类。本质上,原子操作严重依赖于比较与交换(CAS),它是由多数现代CPU直接支持的原子指令。这些指令通常比同步块要快。所以在只需要并发修改单个可变变量的情况下,我建议你优先使用原子类,而不是使用锁机制实现。
AtomicInteger
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
.forEach(i -> executor.submit(atomicInt::incrementAndGet));
stop(executor);
System.out.println(atomicInt.get());// => 1000
使用AtomicInteger
代替 Integer
,我们可以实现线程安全地并行增加数,这里没有使用 synchronizing
关键字。incrementAndGet
方法是原子操作,且是线程安全的,所以可以在多线程中调用。
AtomicInteger
支持不同类型的原子操作。方法updateAndGet()
接受lambda表达式,可以对整数执行任意算术运算。
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
.forEach(i -> {
Runnable task = () ->
atomicInt.updateAndGet(n -> n + 2);
executor.submit(task);
});
stop(executor);
System.out.println(atomicInt.get());// => 2000
方法accumulateAndGet()
接受 IntBinaryOperator
类型的lambda表达式。我们可以使用这种方法并行计算累加0~1000的值,示例如下:
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
IntStream.range(0, 1000)
.forEach(i -> {
Runnable task = () ->
atomicInt.accumulateAndGet(i, (n, m) -> n + m);
executor.submit(task);
});
stop(executor);
System.out.println(atomicInt.get());// => 499500
stop方法的代码如下:
public static void stop(ExecutorService executor) {
try {
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
System.err.println("termination interrupted");
}
finally {
if (!executor.isTerminated()) {
System.err.println("killing non-finished tasks");
}
executor.shutdownNow();
}
}