有人能说出 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);
}
}
答案 0 :(得分:0)
在这个非常精确的例子中(它确实没有用)两个类似乎都是等价的。
使用LongAccumulator,您可以将整个if语句作为lambda表达式传递。 但是:LongAccumulator的java文档声明提供的函数应该是无副作用的,这是不满足的(doSomething写入系统)。
答案 1 :(得分:0)
我想你可能会在这个例子中以与AtomicInteger相同的方式使用LongAccumulator。在这种情况下,答案是否。
当您调用get()等方法时,LongAccumulator仅累积值并计算结果。您还可以清除类似LongAccumulator.reset()方法,当它具有4个值时。但是LongAccumulator中的所有这些方法都不是线程安全的,你可能会得到不可预测的结果,因为你使用多个线程进行读取和更新。
LongAccumulator是好的,当你知道许多不同的线程将是更新值,但读数很少甚至更多时,你应该确保读取或重置只发生在一个线程中,如果你关心同步。 但如果你不这样做,LongAccumulator会更好。例如,当你想要计算统计数据时,因为如果你想得到统计数据,你可能更不可能意味着"统计正好在调用"时,你的意思是"当前&#34 ;结果。 这种推理也适用于LongAdder。
在您的示例中,有两种可能的改进。 首先,您可以使用:
while(true)
if(atomicint.incrementAndGet()==4){doSomething(); atomicint.compareAndSet(4, 0);}
现在你检查一下,你重置了相同的atomicint变量状态。
另一个可能的改进 - 不使用AtomicLong或LongAccumulator,只需使用带有volatile关键字的简单长变量。这将更简单,更适用,因为在这个例子中你没有使用功能(就像我在第一次改进中提到的那样)。
您可以在文档和课程中了解更多信息。来源