【线程池】 2 ExecutorService中 shutdown()、shutdownNow()、awaitTermination() 含义和区别


ExecutorService 是 Java 提供的线程池,也就是说,每次我们需要使用线程的时候,可以通过 ExecutorService 创建线程。
使用 ExecutorService 类时,经常用到 shutdown() 、shutdownNow() 、awaitTermination() 3个方法,下面我们来说说它们的含义和三者的区别 。

一、方法说明

1、shutdown()

停止接收新任务,原来的任务继续执行

1、停止接收新的submit的任务;

2、已经提交的任务(包括正在跑的和队列中等待的),会继续执行完成;

3、等到第2步完成后,才真正停止;

2、shutdownNow()

停止接收新任务,原来的任务停止执行

1、跟 shutdown() 一样,先停止接收新submit的任务;

2、忽略队列里等待的任务;

3、尝试将正在执行的任务interrupt中断,不保证100%中断

4、返回未执行的任务列表;

说明:它试图终止线程的方法是通过调用 Thread.interrupt() 方法来实现的,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt() 方法是无法中断当前的线程的。所以,shutdownNow() 并不代表线程池就一定立即就能退出,它也可能必须要等待所有正在执行的任务都执行完成了才能退出。但是大多数时候是能立即退出的。

3、awaitTermination(long timeOut, TimeUnit unit)

当前线程阻塞,直至解除阻塞并返回值,这个值是线程池中的消息队列是否已经处理结束。

timeout 和 TimeUnit 两个参数,用于设定超时的时间及单位
当前线程阻塞,直到:

  • 等所有已提交的任务(包括正在跑的和队列中等待的)执行完,立即解除阻塞,并返回值;
  • 或者 等超时时间到了(timeout 和 TimeUnit设定的时间),立即解除阻塞,并返回值;
  • 或者 线程被中断,抛出InterruptedException

然后会监测 ExecutorService 是否已经关闭,返回true(shutdown请求后所有任务执行完毕)或false(已超时)

简单来说,不会单独使用,一般在shutdown请求后调用,目的是根据结果做一些特殊操作,比如如果我想要关闭虚机,但是希望消息队列能处理完,即使处理不完,我也可以指定一定的延迟时间,尽量的多完成一些任务,然后再关闭虚机。

我们来测试下延迟参数的例子:
我们创建了100个任务,仅有2个工作线程处理任务,并且每个任务由于休眠2s,处理每个任务需要至少2s,处理完需要约10s;调用awaitTermination后,等待3s,超时立即返回结果(此时是false,线程池尚未关闭)

public class Test2 {
//线程池只有2个线程处理队列
    public static ExecutorService executorService = Executors.newFixedThreadPool(2);

    public static void main(String[] args) throws InterruptedException {
       //创建100个任务
        for (int i = 0; i < 100; i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "   " + new Date());
                    try {
                    //休眠2s,保证任务不能立即被处理完
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
         executorService.shutdown();
        System.out.println("开始等待" + "   " + new Date());
        //延迟3s,阻塞并等待结果
        boolean b = executorService.awaitTermination(3, TimeUnit.SECONDS);
        System.out.println("等待完毕" + "   " + new Date());
        if (b) {
            System.out.println("分线程已经结束");
        }
        //主线程名称,会输出"main"
        System.out.println(Thread.currentThread().getName());
    }
}

我们看下输出:
线程池处理全部任务花费约9s,执行awaitTermination产生的阻塞时间是3s,在阻塞时,任务一直未间断执行,间隔约2s处理2个任务,侧面说明shutdown不会立即停止。最后进程结束,如果不调用shutdown方法,进程不会结束,因此线程池一直存在,进程不会结束

pool-1-thread-2   Wed Apr 29 14:13:42 CST 2020
pool-1-thread-1   Wed Apr 29 14:13:42 CST 2020
开始等待   Wed Apr 29 14:13:42 CST 2020
pool-1-thread-1   Wed Apr 29 14:13:44 CST 2020
pool-1-thread-2   Wed Apr 29 14:13:44 CST 2020
等待完毕   Wed Apr 29 14:13:45 CST 2020
main
pool-1-thread-1   Wed Apr 29 14:13:46 CST 2020
pool-1-thread-2   Wed Apr 29 14:13:46 CST 2020
pool-1-thread-1   Wed Apr 29 14:13:49 CST 2020
pool-1-thread-2   Wed Apr 29 14:13:49 CST 2020
pool-1-thread-2   Wed Apr 29 14:13:51 CST 2020
pool-1-thread-1   Wed Apr 29 14:13:51 CST 2020

三、总结

1、优雅的关闭,用 shutdown()

2、想立马关闭,并得到未执行任务列表,用shutdownNow()

3、 awaitTermination()作用并不是为了关闭线程池,而是配合shutdown或shutdownNow做额外操作。

4、关闭功能 【从强到弱】 依次是:shuntdownNow() > shutdown()

参考https://blog.csdn.net/xiaojin21cen/article/details/81778651
https://blog.csdn.net/sheng_mu555/article/details/80552078

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值