这段代码是对其他有用的代码的简化。为了跟踪循环的进度,我在循环内累积一个 volatile var 计数,并使用 Java 并发的调度线程报告计数值。
def foo {
import java.util.concurrent._
@volatile var count = 0l
val reportRunner = new Runnable { def run() = println(s"report=$count") }
val scheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
val reportRunnerHandle = scheduledExecutorService.scheduleAtFixedRate(reportRunner, 0,1000,TimeUnit.MILLISECONDS)
val l = Stream.fill(100000000)(0)
println(s"start count=$count")
for(i <- 0 until l.size) {
count = count + 1
}
println(s"end count=$count")
reportRunnerHandle.cancel(true)
scheduledExecutorService.shutdown()
}
它为我产生了以下输出:
report=0
start count=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=0
report=60019827
end count=100000000
假设每个报告打印每秒发生一次,但它们会以突发形式发生并且在发生时具有相同的计数。感觉这里缺少一些基本的 JVM 并发问题。或者除了 ScheduledExecutorService 之外,也许还有更可靠的方法可以做到这一点?
这里也没有显示,但我已经尝试使用 AtomicLong 并使用 Actors 来累积计数而不是 volatile 的相同代码,但我得到了相同的结果,这让我怀疑 ScheduledExecutorService。