java8 原子类型——AtomicInteger

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();
    }
}

你可能感兴趣的:(java8~9核心功能)