Java8:在 运行 上发布一个 Thread 示例
Java8: Issue on running a Thread example
我在 winterbe.com 上看到了以下示例,它演示了原子变量的使用。
// From http://winterbe.com/posts/2015/05/22/java8-concurrency-tutorial-atomic-concurrent-map-examples/
public class Test_AtomicInteger {
public static void main(String[] args) {
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);
});
executor.shutdownNow();
System.out.println(atomicInt.get()); // => 2000
}
}
了解如何从线程安全场景中推导出预期值 2000。但是,当我尝试在 eclipse IDE 上执行它时,它每次都会在每个 运行 上给出不同的输出值。想看看是否有人知道为什么它会这样。非常感谢。
shutdownNow
的 JavaDoc 说:
Attempts to stop all actively executing tasks, halts the processing of
waiting tasks, and returns a list of the tasks that were awaiting
execution.
This method does not wait for actively executing tasks to terminate.
Use awaitTermination to do that.
所以这 不会 等待您提交的所有任务完成,因此只需获取成功完成 运行 的线程的结果。
要关闭服务并等待一切完成,请将 shutdownNow
替换为类似以下内容:
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
(您需要从某个地方的 awaitTermination
捕获 InterruptedException
)。
基本上,线程 main
在 所有 执行的任务完成之前调用 shutdownNow
(即使不调用 shutdownNow
你也会仍然没有看到 2000
,因为您仍在执行程序完成之前查询 AtomicInteger
。
您真的想阻塞直到您的执行程序完成或发生超时:
executor.shutdown();
executor.awaitTermination(100, TimeUnit.MILLISECONDS);
如果您仔细查看了 post 的作者,其中摘自定义:
public static void stop(ExecutorService executor) {
try {
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
}
....
正如其他人所说,shutdownNow()
是不合适的,因为它可能导致排队的任务被放弃,同时不等待当前运行ning任务的完成。
正确的顺序应该是 shutdown()
后跟 awaitTermination
,但是,您可以更简单地执行相同的操作:
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.invokeAll(Collections.nCopies(1000, () -> atomicInt.updateAndGet(n -> n + 2)));
System.out.println(atomicInt.get()); // => 2000
executor.shutdown(); // only for cleanup
这里,invokeAll
会调用所有任务,所有任务都可能运行并发,等待所有任务完成。执行器甚至不需要关闭,但可以重复用于其他任务,但是,一旦不再需要它就应该关闭,以清理底层资源。
Collections.nCopies
是获得 List
相同元素的最简单方法,甚至不需要存储空间来保存该数量的引用。
由于invokeAll
需要一个Callable
而不是Runnable
的列表,任务将是Callable
,但这并不影响语义此代码。
我在 winterbe.com 上看到了以下示例,它演示了原子变量的使用。
// From http://winterbe.com/posts/2015/05/22/java8-concurrency-tutorial-atomic-concurrent-map-examples/
public class Test_AtomicInteger {
public static void main(String[] args) {
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);
});
executor.shutdownNow();
System.out.println(atomicInt.get()); // => 2000
}
}
了解如何从线程安全场景中推导出预期值 2000。但是,当我尝试在 eclipse IDE 上执行它时,它每次都会在每个 运行 上给出不同的输出值。想看看是否有人知道为什么它会这样。非常感谢。
shutdownNow
的 JavaDoc 说:
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.
所以这 不会 等待您提交的所有任务完成,因此只需获取成功完成 运行 的线程的结果。
要关闭服务并等待一切完成,请将 shutdownNow
替换为类似以下内容:
executor.shutdown();
executor.awaitTermination(10, TimeUnit.SECONDS);
(您需要从某个地方的 awaitTermination
捕获 InterruptedException
)。
基本上,线程 main
在 所有 执行的任务完成之前调用 shutdownNow
(即使不调用 shutdownNow
你也会仍然没有看到 2000
,因为您仍在执行程序完成之前查询 AtomicInteger
。
您真的想阻塞直到您的执行程序完成或发生超时:
executor.shutdown();
executor.awaitTermination(100, TimeUnit.MILLISECONDS);
如果您仔细查看了 post 的作者,其中摘自定义:
public static void stop(ExecutorService executor) {
try {
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
}
....
正如其他人所说,shutdownNow()
是不合适的,因为它可能导致排队的任务被放弃,同时不等待当前运行ning任务的完成。
正确的顺序应该是 shutdown()
后跟 awaitTermination
,但是,您可以更简单地执行相同的操作:
AtomicInteger atomicInt = new AtomicInteger(0);
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.invokeAll(Collections.nCopies(1000, () -> atomicInt.updateAndGet(n -> n + 2)));
System.out.println(atomicInt.get()); // => 2000
executor.shutdown(); // only for cleanup
这里,invokeAll
会调用所有任务,所有任务都可能运行并发,等待所有任务完成。执行器甚至不需要关闭,但可以重复用于其他任务,但是,一旦不再需要它就应该关闭,以清理底层资源。
Collections.nCopies
是获得 List
相同元素的最简单方法,甚至不需要存储空间来保存该数量的引用。
由于invokeAll
需要一个Callable
而不是Runnable
的列表,任务将是Callable
,但这并不影响语义此代码。