【问题标题】:AtomicInteger or LongAccumulatorAtomicInteger 或 LongAccumulator
【发布时间】:2016-03-12 18:18:40
【问题描述】:

有人可以判断 LongAccumulator 是否可以成为以下示例中 AtomicInteger 的更好替代品吗?

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class IncrementThread implements Runnable{

    AtomicInteger atomicint = new AtomicInteger();

    public IncrementThread(AtomicInteger atominint) {
        this.atomicint = atominint;

    }

    @Override
    public void run() {
        while(true)
            if(atomicint.incrementAndGet()==4){doSomething(); atomicint.set(0);}
    }

    private void doSomething() {
        System.out.println(Thread.currentThread().getName() + " : counter reached to 4");
    }

    public static void main(String[] args) {

        AtomicInteger atomicint = new AtomicInteger();
        IncrementThread incThread1 = new IncrementThread(atomicint);
        IncrementThread incThread2 = new IncrementThread(atomicint);
        IncrementThread incThread3 = new IncrementThread(atomicint);

        ExecutorService threadPool = Executors.newCachedThreadPool();

        threadPool.execute(incThread1);
        threadPool.execute(incThread2);
        threadPool.execute(incThread3);

    }

}

【问题讨论】:

    标签: java multithreading performance java.util.concurrent atomicinteger


    【解决方案1】:

    在这个非常精确的示例中(实际上并没有什么用处),这两个类似乎是等价的。

    使用 LongAccumulator,您可以将整个 if 语句作为 lambda 表达式传递。 但是:LongAccumulator 的 java 文档指出,所提供的函数应该是没有副作用的(doSomething 写入系统输出)。

    【讨论】:

      【解决方案2】:

      我想您可能会以与本例中的 AtomicInteger 相同的方式使用 LongAccumulator。在这种情况下,答案是

      LongAccumulator 仅在调用 get() 之类的方法时累积值并计算结果。您还可以清除类似的 LongAccumulator.reset() 方法,当它有 4 个值时。但是 LongAccumulator 中的所有这些方法都不是线程安全的,并且您可能会得到不可预知的结果,因为您使用多个线程进行读取和更新。

      LongAccumulator 很好,当你知道许多不同的线程会更新值,但读取很少而且更多时,如果你关心同步,你应该确保读取或重置只发生在一个线程中。 但如果你不这样做,LongAccumulator 可能会更好。例如,当您想统计统计信息时,因为如果您想获得统计信息,您更可能不是指“恰好在调用时间的统计信息”,而是指“当前”结果之类的东西。 这个推理也适用于 LongAdder。

      在您的示例中,有两个可能的改进。 首先,您可以使用:

      while(true)
              if(atomicint.incrementAndGet()==4){doSomething(); atomicint.compareAndSet(4, 0);}
      

      现在您检查一下,您重置了 atomicint 变量的相同状态。

      另一个可能的改进 - 不要使用 AtomicLong 或 LongAccumulator,只需使用带有 volatile 关键字的简单 long 变量。它在这里会更简单和更适用,因为在这个例子中你不使用功能(就像我在第一个改进中提到的那样)。

      您可以在文档和类的来源中了解更多

      1. LongAdder
      2. LongAccumulator
      3. About volatile
      4. 最高效 - 来源 :)

      【讨论】:

        猜你喜欢
        • 2017-08-26
        • 1970-01-01
        • 1970-01-01
        • 2016-06-11
        • 1970-01-01
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多