首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java8:运行线程示例时的问题

Java8:运行线程示例时的问题
EN

Stack Overflow用户
提问于 2018-01-23 09:44:41
回答 3查看 320关注 0票数 2

我在winterbe.com上看到了下面的示例,它演示了原子变量的使用。

代码语言:javascript
复制
// 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上执行它时,每次运行时,它都会给出不同的输出值。想看看有没有人知道它为什么会这样。非常感谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-01-23 10:25:17

基本上,线程main是在所有已执行的任务完成之前调用shutdownNow (即使没有调用shutdownNow,仍然看不到2000,因为在执行程序完成之前仍在查询AtomicInteger )。

在执行程序完成或超时之前,您确实希望阻止:

代码语言:javascript
复制
executor.shutdown();
executor.awaitTermination(100, TimeUnit.MILLISECONDS);

如果你仔细看了这篇文章的作者,这是从定义:

代码语言:javascript
复制
 public static void stop(ExecutorService executor) {
    try {
        executor.shutdown();
        executor.awaitTermination(60, TimeUnit.SECONDS);
    }

    ....
票数 2
EN

Stack Overflow用户

发布于 2018-01-23 11:10:55

正如其他人所说的,shutdownNow()是不合适的,因为它可能导致排队的任务被放弃,同时不等待当前正在运行的任务的完成。

一个正确的序列是shutdown(),后面是awaitTermination,但是,您可以做同样简单得多的操作:

代码语言:javascript
复制
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,但这并不影响代码的语义。

票数 3
EN

Stack Overflow用户

发布于 2018-01-23 10:06:39

JavaDoc for shutdownNow说:

尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。 此方法不等待主动执行任务终止。使用awaitTermination来完成这个任务。

因此,这会使而不是等待提交给您完成的所有任务,所以只需获得成功运行的线程的结果即可。

若要关闭服务并等待一切完成,请将shutdownNow替换为如下所示:

代码语言:javascript
复制
executor.shutdown();

executor.awaitTermination(10, TimeUnit.SECONDS);

(您需要从InterruptedException的某个地方捕获awaitTermination )。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48398550

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档