实验讲解-线程池停止执行任务 Executor.execute shutdown awaitTermination shutdownNow()

news2025/7/20 17:13:31

1 Executor.execute

public interface Executor {
在将来的某个时间执行给定的可运行的任务。该可运行的任务可以在新线程、池线程或调用线程中执行,由Executor实现决定。 
参数: command–可运行的任务 
投掷: RejectedExecutionException–如果无法接受执行此任务 
	  NullPointerException–如果命令为空
void execute(Runnable command);
}

2 ExecutorService.shutdown

public interface ExecutorService extends Executor {
1、停止接收新的submit的任务;
2、已经提交的任务(包括正在跑的和队列中等待的),会继续执行完成;
3、等到第2步完成后,才真正停止;
 void shutdown();
}

实例如下:

public class ThreadPoolExecutorCloseTest {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(10,
                20,
                30,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Thread::new,
                new ThreadPoolExecutor.AbortPolicy());

        IntStream.range(0, 20).boxed().forEach(i -> {
            executorService.execute(() -> {
                try {
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println(Thread.currentThread().getName() + " [ " + i + " ] finish done.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        });
        /**
         * 1、停止接收新的submit的任务;
         * 2、已经提交的任务(包括正在跑的和队列中等待的)会继续执行完成;
         * 3、等到第2步完成后,才真正停止;
         */
        executorService.shutdown();
        System.out.println("==============over==============");
    }
}

线程真正停止了!

==============over==============
Thread-15 [ 16 ] finish done.
Thread-9 [ 9 ] finish done.
Thread-16 [ 17 ] finish done.
Thread-7 [ 7 ] finish done.
Thread-12 [ 13 ] finish done.
Thread-5 [ 5 ] finish done.
Thread-4 [ 4 ] finish done.
Thread-3 [ 3 ] finish done.
Thread-1 [ 1 ] finish done.
Thread-11 [ 12 ] finish done.
Thread-6 [ 6 ] finish done.
Thread-17 [ 18 ] finish done.
Thread-10 [ 11 ] finish done.
Thread-13 [ 14 ] finish done.
Thread-18 [ 19 ] finish done.
Thread-8 [ 8 ] finish done.
Thread-14 [ 15 ] finish done.
Thread-2 [ 2 ] finish done.
Thread-0 [ 0 ] finish done.
Thread-12 [ 10 ] finish done.

Process finished with exit code 0

3 ExecutorService.awaitTermination

当前线程阻塞,直到:
1、等所有已提交的任务(包括正在跑的和队列中等待的)执行完;
2、或者 等超时时间到了(timeout 和 TimeUnit设定的时间);
3、或者 线程被中断,抛出InterruptedException
然后会监测 ExecutorService 是否已经关闭,返回true(shutdown请求后所有任务执行完毕)或false(已超时)
boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;

示例如下:

public class ThreadPoolExecutorCloseTest {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = new ThreadPoolExecutor(10,
                20,
                30,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1),
                Thread::new,
                new ThreadPoolExecutor.AbortPolicy());

        IntStream.range(0, 20).boxed().forEach(i -> {
            executorService.execute(() -> {
                try {
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println(Thread.currentThread().getName() + " [ " + i + " ] finish done.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        });
        executorService.shutdown();
        /**
         * 当前线程阻塞,直到:
         * 1、等所有已提交的任务(包括正在跑的和队列中等待的)执行完
         * 2、或者 等超时时间到了(timeout 和 TimeUnit设定的时间)
         * 3、或者 线程被中断,抛出InterruptedException
         * 然后会监测 ExecutorService 是否已经关闭,返回true(shutdown请求后所有任务执行完毕)或false(已超时)
         */
        boolean b = executorService.awaitTermination(30, TimeUnit.SECONDS);
        System.out.println(b);
        System.out.println("==============over==============");
    }

线程真正停止!

Thread-16 [ 17 ] finish done.
Thread-0 [ 0 ] finish done.
Thread-14 [ 15 ] finish done.
Thread-13 [ 14 ] finish done.
Thread-7 [ 7 ] finish done.
Thread-3 [ 3 ] finish done.
Thread-2 [ 2 ] finish done.
Thread-5 [ 5 ] finish done.
Thread-1 [ 1 ] finish done.
Thread-17 [ 18 ] finish done.
Thread-11 [ 12 ] finish done.
Thread-12 [ 13 ] finish done.
Thread-10 [ 11 ] finish done.
Thread-18 [ 19 ] finish done.
Thread-9 [ 9 ] finish done.
Thread-6 [ 6 ] finish done.
Thread-8 [ 8 ] finish done.
Thread-15 [ 16 ] finish done.
Thread-4 [ 4 ] finish done.
Thread-13 [ 10 ] finish done.
true
==============over==============

Process finished with exit code 0

4 shutdownNow()

停止接收新任务,原来的任务停止执行
1、跟 shutdown() 一样,先停止接收新submit的任务;
2、忽略队列里等待的任务;
3、尝试将正在执行的任务interrupt中断;
4、返回未执行的任务列表 — new ArrayBlockingQueue<>(8)

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

public class ThreadPoolExecutorCloseTest {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(10,
                20,
                30,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(8),
                Thread::new,
                new ThreadPoolExecutor.AbortPolicy());

        IntStream.range(0, 20).boxed().forEach(i -> {
            executorService.execute(() -> {
                try {
                    TimeUnit.SECONDS.sleep(10);
                    System.out.println(Thread.currentThread().getName() + " [ " + i + " ] finish done.");
                } catch (InterruptedException e) {
//                    e.printStackTrace();
                }
            });
        });
        shutdownNow(executorService);
        System.out.println("==============over==============");
    }

    private static void shutdownNow(ExecutorService executorService) {
        List<Runnable> runnableList = Lists.newArrayList();
        try {
            runnableList = executorService.shutdownNow();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(runnableList.size());
    }
8
==============over==============

Process finished with exit code 0

shutdown只是将线程池的状态设置为SHUTWDOWN状态,正在执行的任务会继续执行下去,没有被执行的则中断。
而shutdownNow则是将线程池的状态设置为STOP,正在执行的任务则被停止,没被执行任务的则返回。
在这里插入图片描述

shutdownshutdownNow
shutdown调用的是advanceRunState(SHUTDOWN)shutdownNow调用的是(STOP)
shutdown调用的是中断空闲的WorkersshutdownNow调用的是中断所有的Workers
shutdownNow会把所有任务队列中的任务取出来,返回一个任务列表

advanceRunState区别:

  /**
  * 从运行的状态过渡到targetState
  * 如果当前已经大于了targetState,就什么都不做。
  */
    private void advanceRunState(int targetState) {
        for (;;) {
            int c = ctl.get();
            if (runStateAtLeast(c, targetState) ||
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }

targetState参数的使用值只有两个:SHUTDOWN与STOP
SHUTDOWN值为0
STOP值为1<<29 = 2^29

假设传的参数是SHUTDOWN:
ctlOf(targetState, workerCountOf©) = workerCountOf© > 0,一般就是线程池的个数
假设传的参数是STOP: 2^29:
ctlOf(targetState, workerCountOf©) = 2^29 + 2 , 为STOP状态
在这里插入图片描述
在这里插入图片描述

5 长时间未运行完的线程处理

package com.thread.excutor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class ThreadPoolExecutorLongTimeTest {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(10,
                20,
                30,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(8),
                Thread::new,
                new ThreadPoolExecutor.AbortPolicy());

        IntStream.range(0, 10).boxed().forEach(item -> {
            executorService.submit(() -> {
                while (true) {
                }
            });
        });

        try {
            executorService.shutdown();
            executorService.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("===============over================");
    }
}

线程池一直活着,无法停止!

package com.thread.excutor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class ThreadPoolExecutorLongTimeTest {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(10,
                20,
                30,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(8),
                target -> {
                    Thread thread = new Thread(target);
                    thread.setDaemon(true);
                    return thread;
                },
                new ThreadPoolExecutor.AbortPolicy());

        IntStream.range(0, 10).boxed().forEach(item -> {
            executorService.submit(() -> {
                while (true) {
                }
            });
        });

        try {
            executorService.shutdown();
            executorService.awaitTermination(5, TimeUnit.SECONDS); // 最多的期待时间
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("===============over================");
    }
}

ok!设置守护线程的手段!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/37737.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kafka生产者之分区

一、分区好处 &#xff08;1&#xff09;便于合理使用存储资源&#xff0c;每个Partition在一个Broker上存储&#xff0c;可以把海量的数据按照分区切割成一块一块数据存储在多台Broker上。合理控制分区的任务&#xff0c;可以实现负载均衡的效果&#xff1b; &#xff08;2&…

【畅购商城】购物车模块之查看购物车

目录 分析 接口 后端实现 前端实现&#xff1a;显示页面 前端实现&#xff1a;显示购物车信息 分析 用户如果没有登录&#xff0c;购物车存放在浏览器端的localStorage处&#xff0c;且以数组的方式进行存储。用户如果登录了&#xff0c;购物车存放在redis中&#xff0c…

项目实战——对战回放和排行榜

目录 一、天梯积分更新 二、实现对局列表页面 三、前端测试 四、实现查看录像功能 五、实现分页功能 六、后端实现查询排行耪 七、前端展示 八、限制Bot数量 一、天梯积分更新 可以自己定义一下规则 存之前算一下两名玩家的天梯积分 实现更新&#xff0c;实现后重启看一…

挂耳式蓝牙耳机性价比推荐,盘点五款性能高的耳机分享

众所周知&#xff0c;骨传导耳机之所以能够受到人们的喜欢&#xff0c;是因为其佩戴不需入耳&#xff0c;尤其是针对于运动爱好者来说&#xff0c;在户外运动的时候不但可以听见音乐&#xff0c;还可以听见外界的声音&#xff0c;进一步的将危险系数拉低&#xff0c;其次也是因…

音乐信息提取-1-音频表示

音频信号是声音的一种表示&#xff0c;它表示由振动引起的气压随时间的波动&#xff08;数字信号处理-1-关于声音与波&#xff09;。 1 波形与时域 音频信号在时域上的表示就是波形随时间的变化&#xff0c;可以将波形的幅度值理解为声压。 声音是连续的&#xff0c;但数字记…

Spring创建、Bean对象的存储和读取

文章目录1、创建Spring项目1.1 创建Maven项目1.2 添加 Spring 框架支持1.3 添加启动类并添加main&#xff08;非必要步骤&#xff09;2、存储Bean对象2.1 添加Spring配置文件&#xff08;第一次添加&#xff09;2.2 创建Bean对象2.3 将Bean对象注册到Spring容器中3、读取并使用…

秋招挂麻了,就差去送外卖了,10w字Java八股啃完,春招必拿下

最近看到一名前腾讯员工发的帖子&#xff0c;总结的近期面试结果&#xff0c;真的就是那三个字&#xff1a;挂麻了…… 一个毕业后就在腾讯的高级程序员&#xff0c;由于种种原因&#xff0c;离职出来了。趁着金九银十求职季&#xff0c;互联网大厂小厂面试了一圈&#xff0c;感…

AcWing 搜素与图论

搜索 DFS 全排列 代码 #include<iostream> using namespace std;int vis[10], a[10];void dfs(int step, int n) {if (step n 1){for (int i 1; i < n; i)printf("%d ", a[i]);printf("\n");return;}for (int i 1; i < n; i){if (!vis[i…

计算机网络笔记5 传输层

文章目录前言一、运输层概述二、运输层的端口与复用、分用的概念三、UDP协议 和 TCP协议 对比用户数据报协议 UDP&#x1f4a6;&#xff08;User Datagram Protocol&#xff09;传输控制协议 TCP&#x1f4a6;&#xff08;Transmission Control Protocol&#xff09;四、TCP协议…

作用域和作用域链

文章目录1.作用域&#xff08;Scope&#xff09;1.1 什么是作用域1.2 全局作用域1.3 函数作用域1.3 块级作用域2. 作用域链2.1 自由变量2.2 作用域链2.3 *自由变量的取值2.4 作用域与执行上下文的区别3.总结1.作用域&#xff08;Scope&#xff09; 1.1 什么是作用域 当前的执…

easy-rules规则引擎最佳落地实践

写作目的 这是一个头部互联网公司中的一个问题。因为有很多业务产品线&#xff0c;作为一个新人或者团队外的人员是很难区分不同的产品线之间的区别的&#xff0c;因此需要给某个产品线一个描述。但是随着业务的发展&#xff0c;产品线下可能又根据某个字段进一步划分&#xf…

招生CRM系统|基于Springboot实现培训机构招生CRM管理系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

Mongodb操作基础 分片

Mongodb分片 MongoDB分片是MongoDB支持的另一种集群形式&#xff0c;它可以满足MongoDB数据量呈爆发式增长的需求。当MongoDB存储海量的数据时&#xff0c;一台机器可能无法满足数据存储的需求&#xff0c;也可能无法提供可接受的读写吞吐量&#xff0c;这时&#xff0c;我们就…

基于内容的个性化推荐算法

一、什么是推荐算法 随着移动互联网的高速发展与智能手机的普及&#xff0c;海量的有用信息虽然为人们提供了更多的价值&#xff0c;然而信息的泛滥也意味着为了寻找合适的信息必须付出更多的时间成本。事实上&#xff0c;有时候仅仅是浏览和简单的查询来寻找有用的信息变得相…

「强烈收藏」Python第三方库资源大全,1000+工具包

前言 awesome-python 是 vinta 发起维护的 Python 资源列表&#xff0c;内容包括&#xff1a;Web 框架、网络爬虫、网络内容提取、模板引擎、数据库、数据可视化、图片处理、文本处理、自然语言处理、机器学习、日志、代码分析等。 &#xff08;文末送读者福利&#xff09; …

超全!程序员必备的20个学习网站,看这一篇就够了!

之前一直想出个程序员学习清单&#xff0c;终于腾出时间弄出来了&#xff0c;也趁此机会整理了收藏夹。 此篇对于新手程序员比较有用&#xff0c;技术老鸟们也可以查缺补漏。 话不多说&#xff0c;纯纯干货呈上&#xff0c;赶紧点个赞收藏&#xff0c;以后会用得上&#xff01;…

CMake中include_directories的使用

CMake中include_directories命令用于在构建(build)中添加包含目录,其格式如下: include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...]) 将给定的目录添加到编译器(compiler)用于搜索包含文件的目录。相对路径被解释为相对于当前源目录。 包含目录被添加到当前C…

【网络】tcpdump、Wireshark 案例超详细介绍

文章目录网络分层应用层找到服务器的 IP查接口、对象的耗时删除指定网站的Cookie表示层、会话层tcpdump、wireshard传输层telnet: 路径可达性测试nc: 路径可达性测试netstat&#xff1a;查看当前连接状态iftop&#xff1a;查看当前连接的传输速率netstat -s: 查看丢包和乱序的统…

万字 HashMap 详解,基础(优雅)永不过时

本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 提问。 前言 大家好&#xff0c;我是小彭。 在上一篇文章里&#xff0c;我们聊到了散列表的整体设计思想&#xff0c;在后续几篇文章里&#xff0c;我们将以 Java 语言为例&#xff…

【王道计算机组成原理Note】5.5 指令流水线

5 指令流水线 5.1 指令流水的定义 一条指令的执行过程可以分成多个阶段(或过程)。根据计算机的不同&#xff0c;具体的分法也不同。 取指&#xff1a;根据Pc内容访问主存储器&#xff0c;取出一条指令送到IR中。分析&#xff1a;对指令操作码进行译码&#xff0c;按照给定的寻…