1.概述

该ExecutorService框架可以很容易地在处理多线程任务。我们将举例说明我们等待线程完成执行的一些场景。

此外,我们将展示如何正常关闭ExecutorService并等待已经运行的线程完成其执行。

2.Executor关闭后

使用Executor时,我们可以通过调用shutdown()或shutdownNow()方法将其关闭。虽然,它不会等到所有线程都停止执行。

等待现有线程完成执行可以通过使用awaitTermination()方法来实现。

这会阻塞线程,直到所有任务完成执行或达到指定的超时:

public void awaitAfterShutdown(ExecutorService threadPool) {threadPool.shutdown();try {if (!threadPool.awaitTermination(60, TimeUnit.SECONDS)) {threadPool.shutdownNow();}} catch (InterruptedException ex) {threadPool.shutdownNow();Thread.currentThread().interrupt();}}

3.使用CountDownLatch

接下来,让我们看看解决此问题的另一种方法 - 使用CountDownLatch来表示任务的完成。

我们可以使用一个值来初始化它,该值表示在通知所有调用await()方法的线程之前可以递减的次数。

例如,如果我们需要当前线程等待另外N个线程完成执行,我们可以使用N初始化锁存器:

ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(2);
for(int i = 0;i< 2; i++){WORKER_THREAD_POOL.submit(() -> {try {// ...latch.countDown();} catch (InterruptedException e) {Thread.currentThread().interrupt();}});
}
// wait for the latch to be decremented by the two remaining threads
latch.await();

4.使用invokeAll()

我们可以用来运行线程的第一种方法是invokeAll()方法。在所有任务完成或超时到期后,该方法返回Future对象列表。

此外,我们必须注意返回的Future对象的顺序与提供的Callable对象的列表相同:

ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool(10);List<Callable<String>> callables = Arrays.asList(new DelayedCallable("fast thread", 100),new DelayedCallable("slow thread", 3000));long startProcessingTime = System.currentTimeMillis();
List<Future<String>> futures = WORKER_THREAD_POOL.invokeAll(callables);
awaitTerminationAfterShutdown(WORKER_THREAD_POOL);long totalProcessingTime = System.currentTimeMillis() - startProcessingTime;
assertTrue(totalProcessingTime >= 3000);String firstThreadResponse = futures.get(0).get();
assertTrue("fast thread".equals(firstThreadResponse));String secondThreadResponse = futures.get(1).get();
assertTrue("slow thread".equals(secondThreadResponse));

5.使用ExecutorCompletionService

运行多个线程的另一种方法是使用ExecutorCompletionService。它使用提供的ExecutorService来执行任务。

与invokeAll()的一个区别是返回表示执行任务的Futures的顺序。ExecutorCompletionService使用队列按结束顺序存储结果,而invokeAll()返回一个列表,该列表具有与给定任务列表的迭代器生成的顺序相同的顺序:


CompletionService<String> service = new ExecutorCompletionService<>(WORKER_THREAD_POOL);List<Callable<String>> callables = Arrays.asList(new DelayedCallable("fast thread", 100),new DelayedCallable("slow thread", 3000));for (Callable<String> callable : callables) {service.submit(callable);
}

可以使用take()方法访问结果:


long startProcessingTime = System.currentTimeMillis();Future<String> future = service.take();String firstThreadResponse = future.get();long totalProcessingTime = System.currentTimeMillis() - startProcessingTime;assertTrue("First response should be from the fast thread","fast thread".equals(firstThreadResponse));assertTrue(totalProcessingTime >= 100 && totalProcessingTime < 1000);LOG.debug("Thread finished after: " + totalProcessingTime+ " milliseconds");future = service.take();String secondThreadResponse = future.get();totalProcessingTime= System.currentTimeMillis() - startProcessingTime;assertTrue(
"Last response should be from the slow thread","slow thread".equals(secondThreadResponse));assertTrue(totalProcessingTime >= 3000 && totalProcessingTime < 4000);LOG.debug("Thread finished after: " + totalProcessingTime+ " milliseconds");awaitTerminationAfterShutdown(WORKER_THREAD_POOL);

6.结论

根据用例,我们有各种选项来等待线程完成执行。

一个CountDownLatch当我们需要一种机制来通知一组由其他线程执行的操作已完成一个或多个线程是非常有用的。

当我们需要尽快访问任务结果时,ExecutorCompletionService非常有用,当我们想要等待所有正在运行的任务完成时,其他方法。


关注公众号:「Java知己」,每天更新Java知识哦,期待你的到来!

  • 发送「1024」,免费领取 30 本经典编程书籍。
  • 发送「Group」,与 10 万程序员一起进步。
  • 发送「JavaEE实战」,领取《JavaEE实战》系列视频教程。
  • 发送「玩转算法」,领取《玩转算法》系列视频教程。

ExecutorService等待线程完成后优雅结束相关推荐

  1. python等待线程结束_如何等待线程完成后再继续

    我需要在另一个线程中运行一个函数,并获取该函数的返回值以将其保存到主线程中的一个变量中.基本上,我的代码调用该函数,该函数通过串行端口与天平通信,等待并获取响应,解析响应,并以浮点形式返回响应.我需要 ...

  2. python等待线程结束_python线程join

    几个事实 1 python 默认参数创建线程后,不管主线程是否执行完毕,都会等待子线程执行完毕才一起退出,有无join结果一样 2 如果创建线程,并且设置了daemon为true,即thread.se ...

  3. python的线程如何启用和结束_python线程进程

    操作系统 一 为什么要有操作系统? 现代计算机系统是由一个或者多个处理器,主存,磁盘,打印机,键盘,鼠标显示器,网络接口以及各种其他输入 输出设备组成的复杂系统,每位程序员不可能掌握所有系统实现的细节 ...

  4. qt 等待线程结束_实战PyQt5: 128-使用多线程进行并行处理

    多线程是实现并行处理的重要手段,在GUI编程中,经常需要将耗费任务分离,用单独的线程来处理,避免对主线程造成影响(最常见的影响就是会造成主界面无法响应的假死现象).在Qt中,最常用的多线程一般是通过继 ...

  5. java 等待线程结束 框架_深入理解Java多线程与并发框架——线程的状态

    欢迎关注专栏<Java架构筑基>--专注于Java技术的研究与分享!Java架构筑基​zhuanlan.zhihu.comJava架构筑基--专注于Java技术的研究与分享! 后续文章将首 ...

  6. java 等待线程池结束_如何等待java线程池中所有任务完成

    一.等待线程池所有线程完成: 有时候我们需要等待java thread pool中所有任务完成后再做某些操作,如想要等待所有任务完成,仅需调用threadPool.awaitTermination() ...

  7. python结束线程_2018-01-02 如何优雅地终止python线程

    前言 · 零 我们知道,在python里面要终止一个线程,常规的做法就是设置/检查 --->标志或者锁方式来实现的. 这种方式好不好呢? 应该是不大好的!因为在所有的程序语言里面,突然地终止一个 ...

  8. Java线程池如何优雅地等待所有任务执行完

    随着项目的体量越来越大,对代码的执行效率要求越来越高,在实际应用过程中我们会经常使用线程池. 那么如果线程池嵌入在业务代码中,如何正确的等待线程池执行完,在执行后续操作呢?或者想要获取执行结果有应该怎 ...

  9. 主线程等待线程池所有任务完成

    http://blog.chenlb.com/2008/12/main-thread-wait-all-sub-thread-finish-task-in-thread-pool.html 原文出处: ...

最新文章

  1. Android Kotlin Exception处理
  2. 04. Web大前端时代之:HTML5+CSS3入门系列~HTML5 表单
  3. 关于python测试webservice接口的视频分享
  4. numpy 矩阵与向量相乘_高能!8段代码演示Numpy数据运算的神操作
  5. 减治法解决约瑟夫斯问题(JAVA)
  6. Linux每个目录的介绍
  7. eclipse tomcat插件安装
  8. SpringCloud工作笔记071---mysql字符集 utf8 和utf8mb4 的区别_utf8是不能存储emoji表情字符集的
  9. 基于Pandas的数据清洗
  10. [SSH] 传输文件
  11. bio、nio、aio及select、poll、epoll
  12. flash游戏转换html5,一键转换——介绍我做的flash转html5工具LavaH
  13. Word如何自动多级编号
  14. 动作捕捉协助中国电力科学研究院建立边云协同电力自主巡检系统
  15. 微信小程序实现自动定位
  16. 技术干货 | 录屏采集实现教程 —— Android端
  17. 消费返利模式的众筹玩法轻松无压力
  18. numpy.arange()参数含义
  19. 《SAP HANA平台应用开发》—第2章2.1节熟悉HANA开发环境
  20. Excel 2010 VBA 入门 086 数据处理之获取交叉查询结果表

热门文章

  1. android手机屏幕总是闪烁,手机屏幕闪烁是什么原因
  2. shopify上传商品价格怎么改美元美金$
  3. 发票专用驱动sjz_停机前未勾选完的发票,升完级后这样操作
  4. cent7 安装 notepadqq
  5. 如何通过API接口获取item_get_pro - 获得淘宝商品详情高级版
  6. php截断,php include 路径截断漏洞的利用
  7. android camera使用ISO值录制视频
  8. ModelSim SE简明操作指南
  9. 实用Python程序设计测验:数字统计
  10. Complex Multiplier IP 使用教程(源码)