并发学习25--多线程 ThreadPoolExecutor

类图:定义了一些重要的接口和实现类

线程池的几种状态:

ThreadPoolExecutor构造方法

1.救急线程

线程池中会有核心线程和救急线程;救急线程数=最大线程数-核心线程数。而救急线程会在阻塞队列已经占满的情况下,执行下一个即将要被拒绝策略执行任务。且救急线程在执行完任务后的KeepAliveTime时间内,如果没有执行新的任务,那么就会从线程池remove这个线程。不同于核心线程是一直存在于线程池中的。

救急线程是懒惰创建的,只有当有界阻塞队列满的时候才会创建救急线程执行任务。如果阻塞队列是无界的,那么永远不会创建救急线程。

2.核心线程

会优先使用核心线程来执行任务,且核心线程是懒惰创建。当核心线程执行完任务后,并不会主动结束自己,而是还在运行中。需要特殊处理使之结束。

3.拒绝策略

当救急线程被占用完后再来新的任务会由拒绝策略完成。

4.JDK提供线程池执行过程

4.JDK提供的拒绝策略

NewFixedThreadPool 固定大小线程池

1.介绍

2.代码示例
import lombok.extern.slf4j.Slf4j;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j(topic = "TC41")
public class TC41 {public static void main(String[] args) throws InterruptedException{ExecutorService pool = Executors.newFixedThreadPool(2, new ThreadFactory() {private AtomicInteger threadPoolNumber = new AtomicInteger(1);//使用ThreadFactory自定义线程名@Overridepublic Thread newThread(Runnable r) {return new Thread(r,"Pool_t"+threadPoolNumber.getAndIncrement());}});pool.execute(()->{log.debug("1");});pool.execute(()->{log.debug("2");});pool.execute(()->{log.debug("3");});//result: 且程序不会结束,因为核心线程只是执行完任务,但并没有结束//11:10:02.144 [Pool_t2] DEBUG TC41 - 2//11:10:02.144 [Pool_t1] DEBUG TC41 - 1//11:10:02.147 [Pool_t2] DEBUG TC41 - 3}
}

NewCachedThreadPool 带缓冲的线程池

1.介绍

若每个任务执行时间都很长的话会创建太多线程,消耗CPU影响性能。

2.SynchronousQueue

SynchronousQueue指t1线程在Queue里放任务时放不进去,只能阻塞在外面,当t2线程来取的时候,就可以把任务取走了。意味着:该队列就是为了阻塞一个任务且不用拒绝策略,只等待线程来执行。当SynchronousQueue配合NewCachedThreadPool执行时,就是每当阻塞一个任务就创建一个救急线程。

SynchronousQueue使用代码示例
import lombok.extern.slf4j.Slf4j;import java.util.concurrent.SynchronousQueue;@Slf4j(topic = "TC42")
public class TC42 {public static void main(String[] args) {SynchronousQueue queue = new SynchronousQueue();new Thread(()->{try {log.debug("put 1....");//当执行put()后被阻塞住,当take()执行完后,put()才执行完毕queue.put(1);log.debug("putted 1....");log.debug("put 2....");queue.put(2);log.debug("putted 2....");} catch (InterruptedException e) {e.printStackTrace();}},"t1").start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{log.debug("get 1...");try {queue.take();} catch (InterruptedException e) {e.printStackTrace();}},"t2").start();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(()->{log.debug("get 2...");try {queue.take();} catch (InterruptedException e) {e.printStackTrace();}},"t3").start();}
}

 NewSingleThreadExecutor 单线程执行器

线程异常后,线程池会重新创建新的线程
import lombok.extern.slf4j.Slf4j;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j(topic = "TC43")
public class TC43 {public static void main(String[] args) throws InterruptedException {test1();//result: 线程1抛出异常停止后,线程池又创建了一个线程2去执行后面的codes //14:15:44.489 [pool-1-thread-1] DEBUG TC43 - 1//Exception in thread "pool-1-thread-1" 14:15:44.493 [pool-1-thread-2] DEBUG TC43 - 2//14:15:44.493 [pool-1-thread-2] DEBUG TC43 - 3}public static void test1() throws InterruptedException{ExecutorService service = Executors.newSingleThreadExecutor();service.execute(()->{log.debug("1");int i=1/0;});service.execute(()->{log.debug("2");});service.execute(()->{log.debug("3");});}
}

提交任务

 Future<T> Submit

有一个Future类型的返回值

import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;@Slf4j(topic = "TC44")
public class TC44 {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService pool = Executors.newFixedThreadPool(2);Future<String> future = pool.submit(()->{log.debug("running");Thread.sleep(1000);return "ok";});log.debug("{}",future.get());}
}
List<Future<T>> invokeAll()

执行集合中所有线程,并返回所有返回值到一个集合里。

import lombok.extern.slf4j.Slf4j;import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;@Slf4j(topic = "TC45")
public class TC45 {public static void main(String[] args) throws InterruptedException {ExecutorService pool = Executors.newFixedThreadPool(2);List<Future<Object>> futures = pool.invokeAll(Arrays.asList(()->{log.debug("begin...");Thread.sleep(1000);return "1";},()->{log.debug("begin...");Thread.sleep(500);return "2";},()->{log.debug("begin...");Thread.sleep(2000);return "3";}));futures.forEach(f->{try {log.debug("{}",f.get());} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}});}
}
Object invokeAny()

集合中哪个线程结束最早返回哪个线程,其余线程停止执行任务。

0.5S后打印结果,因为第二个callable线程结束最早只等待了0.5S.

import lombok.extern.slf4j.Slf4j;import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@Slf4j(topic = "TC46")
public class TC46 {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService pool = Executors.newFixedThreadPool(3);Object o = pool.invokeAny(Arrays.asList(()->{log.debug("begin 1....");Thread.sleep(1000);log.debug("end 1....");return "1";},()->{log.debug("begin 2....");Thread.sleep(500);log.debug("end 2....");return "2";},()->{log.debug("begin 3....");Thread.sleep(800);log.debug("end 3....");return "3";}));log.debug("{}",o.toString());}
}

关闭线程池

shutdown()

 不会等待正在运行的线程,等它们运行结束,就会自己停止

shutdownNow()

其他终结方法

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

07、JS实现:用回溯法实现数组全排列的算法(一步一步剖析,很详细)

回溯法实现数组全排列的算法 Ⅰ、回溯法实现数组全排列&#xff1a;1、题目描述&#xff1a;2、解题思路&#xff1a;3、实现代码&#xff1a; Ⅱ、小结&#xff1a; Ⅰ、回溯法实现数组全排列&#xff1a; 1、题目描述&#xff1a; 给定⼀个 没有重复 数字的序列&#xff0c;…

Kimi 200万字爆火,通义加码1000万,阿里笑而不语

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 我怎么感觉Kimi是一个“网红”产品呢?在没有任何预兆情况下&#xff0c;国产AI大模型Kimi突然爆火&#xff0c;最近我在很多平台上看到了Kimi的广告&#xff0c;感觉到处都在吹这个产品。 看见上面的新闻了吧&a…

使用Spark单机版环境

在Spark单机版环境中&#xff0c;可通过多种方式进行实战操作。首先&#xff0c;可使用特定算法或数学软件计算圆周率π&#xff0c;并通过SparkPi工具验证结果。其次&#xff0c;在交互式Scala版或Python版Spark Shell中&#xff0c;可以进行简单的计算、打印九九表等操作&…

VRAY渲染设置大神参数(建议收藏)

3dmax效果图云渲染平台——渲染100以3ds Max 2024、VR 6.2、CR 11.2等最新版本为基础&#xff0c;兼容fp、acescg等常用插件&#xff0c;同时LUT滤镜等参数也得到了同步支持。注册填邀请码【7788】可领30元礼包和免费渲染券哦~ 公用&#xff1a;输出大小&#xff1a;一般小图50…

JavaScript进阶5之垃圾回收(计算机组成、解释与编译、JavaScript引擎、垃圾回收、内存管理)、运行机制(浏览器进程分类、浏览器事件循环)

垃圾回收&运行机制 垃圾回收计算机组成解释与编译JavaScript引擎V8引擎 垃圾回收引用计数法标记清除&#xff08;mark-sweep&#xff09;算法 内存管理新生代 运行机制浏览器进程分类&#xff1a;浏览器事件循环宏任务微任务整体流程浏览器事件循环案例一案例二 垃圾回收 …

SpringBoot中处理校验逻辑的两种方式:Hibernate Validator+全局异常处理

最近正在开发一个校园管理系统&#xff0c;需要对请求参数进行校验&#xff0c;比如说非空啊、长度限制啊等等&#xff0c;可选的解决方案有两种&#xff1a; 一种是用 Hibernate Validator 来处理一种是用全局异常来处理 两种方式&#xff0c;我们一一来实践体验一下。 一、…

Oracle Data Guard部署

Oracle的主备DG搭建 1. 修改主机名,同步时间 主库IP&#xff1a;192.168.100.137 备库IP&#xff1a;192.168.100.138配置主机名(主库) Hostname zygjpdb vim /etc/hosts 192.168.100.137 zygjpdb 192.168.100.138 zygjsdbvim /etc/sysconfig/network HOSTNAMEzygjpdb ------…

TransformControls 是 Three.js 中的一个类,用于在网页中进行 3D 场景中物体的交互式操作。

demo案例 TransformControls 是 Three.js 中的一个类&#xff0c;用于在网页中进行 3D 场景中物体的交互式操作。让我们来详细讲解它的输入参数、输出、属性和方法&#xff1a; 输入参数&#xff1a; TransformControls 构造函数通常接受两个参数&#xff1a; camera&#…

YAPI接口自动鉴权功能部署详解

安装准备 以下操作&#xff0c;默认要求自己部署过yapi&#xff0c;最好是部署过yapi二次开发环境。 无论是选择在线安装或者是本地安装&#xff0c;都需要安装client工具。 1、yapi-cli&#xff1a;npm install yapi-cli –g&#xff0c; 2、安装后将文件夹nodejs/node_gl…

JavaScript 打印教程(第二部分)设置编码

JavaScript 打印教程&#xff08;第二部分&#xff09;设置编码 在进行文本打印时&#xff0c;尤其是涉及到中文或其他特殊字符时&#xff0c;正确的编码设置是非常重要的。不同的打印机支持不同的指令集&#xff0c;因此了解并使用适合您打印机的指令集是关键。本篇教程继续使…

使用 python 拆分 excel 文件

文章目录 1、安装虚拟环境&#xff08;在特定文件夹内&#xff09;2、脚本 split.sh3、运行脚本&#xff08;在特定文件夹内&#xff09;4、结果 1、安装虚拟环境&#xff08;在特定文件夹内&#xff09; brew install python3 xcode-select --install python3 -m venv my_pan…

【Python】Selenium自动化测试框架

设计思路 本文整理归纳以往的工作中用到的东西&#xff0c;现汇总成基础测试框架提供分享。 框架采用python3 selenium3 PO yaml ddt unittest等技术编写成基础测试框架&#xff0c;能适应日常测试工作需要。 1、使用Page Object模式将页面定位和业务操作分开&#xff0…

【蓝牙协议栈】【SMP】安全管理协议

1. SMP概念 SMP&#xff08;Security Manager Protocol&#xff09;即安全管理协议。SMP 是蓝牙用来进行安全管理的&#xff0c;其定义了配对和 Key&#xff08;可以理解成密钥&#xff09;的分发过程的实现&#xff0c;以及用于 实现这些方法的协议和工具。SMP 的内容主要是配…

探索网络分析:图论算法介绍及其如何用于地理空间分析

网络分析简介 出售真空吸尘器的挨家挨户的推销员列出了一个潜在客户,分布在邻近他的几个城市中。他想离开家,参观每个潜在客户,然后返回家园。他可以采取的最短、最有效的路线是什么? 这种情况被称为旅行推销员问题,它可能是优化中研究最深入的问题(旅行推销员问题,2023…

【Unity】调整Player Settings的Resolution设置无效

【背景】 Build时修改了Player Settings下的Resolution设置&#xff0c;但是再次Building时仍然不生效。 【分析】 明显是沿用了之前的分辨率设定&#xff0c;所以盲猜解决办法是Build相关的缓存文件&#xff0c;或者修改打包名称。 【解决】 实测修改版本号无效&#xf…

推特社交机器人分类

机器人有不同的种类。 cresci-17数据集中的三种不同的机器人类:传统垃圾机器人、社交垃圾机器人和假追随者。 传统的垃圾邮件机器人会生成大量推广产品的内容&#xff0c;并且可以通过频繁使用的形容词来检测; 社交垃圾邮件倾向于攻击或支持政治候选人&#xff0c;因此情绪是一…

鸿蒙HarmonyOS应用开发之Node-API简介

场景介绍 OpenHarmony Node-API是基于Node.js 8.x LTS的 Node-API 规范扩展开发的机制&#xff0c;为开发者提供了ArkTS/JS与C/C模块之间的交互能力。它提供了一组稳定的、跨平台的API&#xff0c;可以在不同的操作系统上使用。 本文中如无特别说明&#xff0c;后续均使用Nod…

顶会热点!迁移学习9个结合创新思路,让审稿人眼前一亮

为更灵活、更高效地解决各种复杂和动态变化问题&#xff0c;研究者开始着眼于将迁移学习与其他技术相结合。 这种结合充分发挥了迁移学习的优势&#xff0c;如知识转移、数据效率和加速学习过程等&#xff0c;让模型能够从更高的基准开始学习&#xff0c;更快地适应新任务&…

多源异构数据种类有哪些?企业该如何利用融合多源数据

随着信息时代的来临&#xff0c;数据的重要性愈发凸显&#xff0c;企业、组织和个人从各种渠道汲取丰富的信息。然而&#xff0c;这些数据往往源自不同的渠道&#xff0c;呈现异构的形式&#xff0c;为数据融合带来了巨大挑战。本文旨在深入研究多源异构数据的种类&#xff0c;…

人工智能课程小结

人工智能的各种认识论 对人工智能理论的争论 符号主义 (1)人类认知和思维的基本单元是符号 (2)计算机也是—个物理符号系统 (3)认知过程就是在符号表示上的一种运算。 连接主义 (1)人的思维单元是神经元 (2)人脑不同于电脑 行为主义 (1)智能取决于感知和行动&#xf…