Java之线程池
目录
一.上节复习
1.阻塞队列
二.线程池
1.什么是线程池
2.为什么要使用线程池
3.JDK中的线程池
三.工厂模式
1.工厂模式的目的
四.使用线程池
1.submit()方法
2.模拟两个阶段任务的执行
五.自定义一个线程池
六.JDK提供线程池的详解
1.如何自定义一个线程池?
2.创建线程池的构造方法的参数及含义
3.描述线程池的工作原理
4.拒绝策略
5.为什么不推荐使用系统自带的线程池
七.自定义线程池
1.自定义线程池
2.拒绝策略测试
一.上节复习
上节内容指路:Java之阻塞队列和消息队列
1.阻塞队列
基于阻塞队列和生产者消费者模型可以实现消息队列
wait()和notify()使用的时机
虚假唤醒:把wait()的判断条件放在一个while循环里面,唤醒之后需要重新检查等待条件
二.线程池
1.什么是线程池
JDBC编程中,通过DataSource获取Connection就用到了池(数据库连接池)的概念 数据库连接池中有一些已经建立了连接(输入完账号密码的状态)的connection
当Java程序需要数据库连接时,只需要从数据库连接池中获取到一个空闲的连接进行使用
当Java程序使用完连接之后,就会将当前连接返还给数据库连接池
线程池里放的是线程本身,当程序启动时就创建若干个线程,如果有任务就处理,没有任务就阻塞等待.
2.为什么要使用线程池
为了减少系统创建线程的开销
如果我们不使用线程池,每一次使用创建线程,销毁线程(用户态到内核态),很浪费系统的资源,而且再多线程的环境下,我们一次使用可能是多个线程,多个一起创建很浪费系统的资源,大大减少了系统执行的效率.使用线程池,每一次到池中拿到一个线程,只需要涉及到用户态的操作.
3.JDK中的线程池
1. 用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新的线程,如果线程空闲60秒将收回并移出缓存
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
2. 创建一个操作无界队列且初始线程数为n的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
无界队列: 指的是对队列中的元素个数不加限制,可能出现内存被消耗殆尽的情况
3. 创建一个操作无界队列且只有一个工作线程的线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
4. 创建一个单线程执行器,可以在给定时间后执行或定期执行。
ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
5. 创建一个指定大小的线程池,可以在给定时间后执行或定期执行。
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
6. 创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行地处理任务不保证处理顺序
ExecutorService executorService = Executors.newWorkStealingPool();
三.工厂模式
1.工厂模式的目的
解决构造方法创建对象的缺陷
以下情况会发生问题,(id,name)和(age,name)会出现相同的参数列表不能够重载,因此不能同时书写这两个构造方法
我们可以通过两个静态方法来进行创建
class Student {private int id;private int age;private String name;public static Student createByIdAndName(int id, String name) {Student student = new Student();student.setId(id);student.setName(name);return student;}public static Student createByAgeAndName(int age, String name) {Student student = new Student();student.setAge(age);student.setName(name);return student;}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
四.使用线程池
1.submit()方法
通过submit方法可以看出我们可以提交任务到线程池,线程池中提供线程进行执行任务.
2.模拟两个阶段任务的执行
public class Demo03_ThreadPoolUse {public static void main(String[] args) throws InterruptedException {//创建一个初始大小为3的线程池ExecutorService threadPool = Executors.newFixedThreadPool(3);for (int i = 0; i < 10; ++i) {int taskId = i;threadPool.submit(() -> {System.out.println("我是任务:" + taskId+","+Thread.currentThread().getName());});}//模拟线程等待一段时间TimeUnit.SECONDS.sleep(5);System.out.println("第二阶段开始");for (int i = 10; i < 20; ++i) {int taskId = i;threadPool.submit(() -> {System.out.println("我是任务:" + taskId+","+Thread.currentThread().getName());});}}
}
打印的内容:
注意:此时程序并没有结束,在等待其他任务提交到线程池进行执行
五.自定义一个线程池
1.可以提交任务到线程池,那么就需要一种数据结构来保存任务----可以考虑使用阻塞队列
2.创建线程池需要指定初始的线程数量,这些线程不断的扫描阻塞队列,如果有任务就立即执行.
可以考虑使用线程池对象的构造方法,接收要创建线程的数据并在构造方法中完成线程的创建
public class MyThreadPool {//定义一个阻塞队列来保存要执行的任务BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(3);//提供一个方法,用来提交任务public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}//构造方法完成线程的初始化public MyThreadPool(int capacity) {if (capacity <= 0) {throw new IllegalArgumentException("capacity is illegal");}//完成线程的创建,扫描队列,取出任务并执行for (int i = 0; i < capacity; i++) {Thread thread = new Thread(() -> {while (true) {//取出任务try {Runnable take = queue.take();take.run();} catch (InterruptedException e) {throw new RuntimeException(e);}}});thread.start();}}
}
测试自定义的线程池:
public class Demo04_MyThreadPool {public static void main(String[] args) throws InterruptedException {//创建一个初始大小为3的线程池MyThreadPool threadPool = new MyThreadPool(3);for (int i = 0; i < 10; ++i) {int taskId = i;threadPool.submit(() -> {System.out.println("我是任务:" + taskId + "," + Thread.currentThread().getName());});}//模拟线程等待一段时间TimeUnit.SECONDS.sleep(2);System.out.println("第二阶段开始");for (int i = 10; i < 20; ++i) {int taskId = i;threadPool.submit(() -> {System.out.println("我是任务:" + taskId + "," + Thread.currentThread().getName());});}}
}
打印结果:
六.JDK提供线程池的详解
1.如何自定义一个线程池?
通过工厂方法获得的线程池最终都是创建一个ThreadPoolExecutor对象
2.创建线程池的构造方法的参数及含义
- int corePoolSize 核心线程数,创建线程是包含的最小线程数
- int maximumPoolSize 最大线程数,也叫临时线程数(核心线程数不够时,允许创建最大的线程数)
- long keepAliveTime 临时空闲时长,超过这个时间自动释放
- TimeUnit unit 空闲的时间单位,和keepAliveTime一起使用
- BlockingQueue<Runnable> workQueue 用来保存任务的阻塞队列
- ThreadFactory threadFactory 线程工厂,如何去创建线程
- RejectedExecutionHandler handler 拒绝策略,触发的时机,当线程池处理不了过多的任务
3.描述线程池的工作原理
即上面七个参数如何搭配使用
先来举一个现实中的例子帮助我们理解工作原理:饭店老板根据人流量安排桌子数(线程数)
1.饭店里面初始有五张桌子(核心线程数为5)
2.下午3点,人数少于5,5张桌子足够接待顾客(核心线程数大于任务数)
3.到了晚饭点,人数大于5,不够接待顾客,顾客需要拿号排队等待(向阻塞队列加入任务)
4.排号人数过多,老板在饭店门口临时加了10张桌子(创建10个临时线程)
5.在用餐高峰期,门口10张桌子全部用完,排号也特别多,就让新来的顾客下次再来(执行拒绝策略)
6.当人数减少,门口10张桌子空了下来,过了半小时还没人来,将10张桌子回收(临时线程达到空闲时常,回收临时线程)
- 当任务添加到线程池中时,先判断任务数是否大于核心线程数,如果不大于,直接执行任务
- 任务数大于核心线程数,则加入阻塞队列
- 当阻塞队列满了之后,会创建临时线程,会按照最大线程数,一次性创建到最大线程数
- 当阻塞队列满了并且临时线程也创建完成,再提交任务,就会执行拒绝策略.
- 当任务减少,临时线程达到空闲时长时,会被回收.
4.拒绝策略
AbortPolicy:直接拒绝任务的加入,并且抛出RejectedExecutionException异常
CallerRunsPolicy:返回给提交任务的线程执行
DiscardOldestPolicy:舍弃最老的任务
DiscardPolicy:舍弃最新的任务
根据自己的业务场景选择合适的拒绝策略
5.为什么不推荐使用系统自带的线程池
1.由于使用了无界队列,可能会有内存耗尽的风险
默认是长度最大的阻塞队列
2.临时线程数无法控,也可能会存在资源耗尽
七.自定义线程池
1.自定义线程池
public class Demo_05_Create {public static void main(String[] args) throws InterruptedException {//创建线程池并指定参数ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2, 5, 1, TimeUnit.SECONDS,new LinkedBlockingQueue<>(10), new ThreadPoolExecutor.AbortPolicy());for (int i = 0; i < 10; ++i) {int taskId = i;threadPool.submit(() -> {System.out.println("我是任务:" + taskId + "," + Thread.currentThread().getName());});}//模拟线程等待一段时间TimeUnit.SECONDS.sleep(5);System.out.println("第二阶段开始");for (int i = 10; i < 20; ++i) {int taskId = i;threadPool.submit(() -> {System.out.println("我是任务:" + taskId + "," + Thread.currentThread().getName());});}}
}
2.拒绝策略测试
1.AbortPolicy
将阻塞队列的大小改为1,然后在执行方法
2.CallerRunsPolicy
返回给调用者main方法线程
3.DiscardOldestPolicy
抛弃了一部分的任务,老的
4.DiscardPolicy
抛弃了一部分的任务,新的
相关文章:

Java之线程池
目录 一.上节复习 1.阻塞队列 二.线程池 1.什么是线程池 2.为什么要使用线程池 3.JDK中的线程池 三.工厂模式 1.工厂模式的目的 四.使用线程池 1.submit()方法 2.模拟两个阶段任务的执行 五.自定义一个线程池 六.JDK提供线程池的详解 1.如何自定义一个线程池? 2.创…...
让你的网站变得更智能 - B2 Pro主题问答模块新增OpenAI ChatGPT机器人自动回答功能
作为一个网站管理员,你一定会希望能够给你的用户提供更多、更好的服务。那么,你是否曾经想过为你的B2 Pro主题问答模块新增一个智能机器人自动回答功能呢?相信你一定想要这个功能,因为它能够大大提升你网站的用户体验。 现在,我们为你提供了一个好消息。我们已经为B2 Pro…...

仓库信息管理系统设计与实现
一、数据库设计 1.数据库模型设计概览 2.数据库表设计 ①depository 描述: 该表存储仓库的信息,比如仓库名称,仓库地址和仓库介绍 表结构: 序号 字段名 数据类型 主键 非空 默认值 描述 1 id INT(10) 是 是 2…...

初识Java多线程编程
文章目录 一、线程的状态二、线程的常见属性三、多线程编程Thread类常用构造方法1.继承Thread类2.实现Runnable接口3.匿名内部类实现4.lambda 表达式创建 Runnable 子类对象 四、线程的常见方法 一、线程的状态 //线程的状态是一个枚举类型 Thread.State public class ThreadS…...

最新入河排污口设置论证、水质影响预测与模拟、污水处理工艺分析及典型建设项目入河排污口方案报告书实例分析
随着水资源开发利用量不断增大,全国废污水排放量与日俱增,部分河段已远远超出水域纳污能力。近年来,部分沿岸入河排污口设置不合理,超标排污、未经同意私设排污口等问题逐步显现,已威胁到供水安全、水环境安全和水生态安全&#x…...

awk指令的详细指南
目录 工作原理 命令格式 awk常见的内建变量(可直接用)如下所示 按行输出文本 按字段输出文本 通过管道、双引号调用 Shell 命令 示例 CPU使用率 数组 编辑统计文件的内容出现的次数 使用awk 统计secure 访问日志中每个客户端IP的出现次数? …...

解密Netty中的Reactor模式
文章目录 单线程Reactor模式多线程Reactor模式Reactor模式中IO事件的处理流程Netty中的通道ChannelNetty中的反应器ReactorNetty中的处理器HandlerNetty中的通道Channel和处理器Handler的协作组件Pipeline Reactor(反应器)模式是高性能网络编程在设计和架构方面的基础模式.Doug…...
这是一个黑科技:C++爬虫~(文末报名C/C++领域新星计划)
目录 写在前面 完整代码 这里必看!! 写在最后 写在前面 现在所有人都知道万能的Python可以做机器学习,可以做人工智能,可以爬取各种小网站,但是你不知道,基于C++的正则表达式早就能够爬取各种网络数据啦!!你没猜错,阿玥将在这篇文章中简介怎么用C...

2023 年第八届数维杯数学建模挑战赛 赛题浅析
为了更好地让大家本次数维杯比赛选题,我将对本次比赛的题目进行简要浅析。本次比赛的选题中,研究生、本科组请从A、B题中任选一个 完成答卷,专科组请从B、C题中任选一个完成答卷。这也暗示了本次比赛的难度为A>B>C 选题人数初步估计也…...

Spring Boot单元测试
什么是单元测试? 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证的过程就叫单元测试。 单元测试是开发人员编写的一小段代码,用于检验被测代码的一个很小的、很明确的(代码) 功能是否正确。执行单元测试就是为了证明某…...

实景三维浪潮翻涌,新技术“席卷”石家庄!
5月11日,“全自主、全流程、全覆盖”2023实景三维新技术研讨会石家庄站暨航测与遥感学术交流会在石家庄凯旋金悦大酒店圆满举行。 本次会议由中国测绘学会、中国地理信息产业协会指导,河北省测绘学会、河北省地理信息产业协会主办,武汉大势智…...
【Python】使用小脚本
本文整理了我在学习和工作中用到的实用python脚本,希望也能帮助到需要的小伙伴~ 文章目录 视频格式转换顺序遍历文件夹中的文件 视频格式转换 安装视频处理库moviepy pip install moviepy安装FFmpeg(FFmpeg是一个开源的多媒体框架,moviepy…...
技术日志2023-5-18
1、Java远程调试 可参考:https://kefeng.wang/2018/03/06/idea-remote-debug/ 2、用户中心这样的基础项目有什么用,感觉非常鸡肋。 今天开发讨论中涉及到了用户中心,感觉在项目中使用用户中心只是给业务系统发一个token,业务系…...
JUC之锁
公平锁、非公平锁 公平锁指的是多线程按照申请锁的顺序来获取锁; 非公平锁指的是多线程不按照申请锁的顺序来获取锁。可能会出现优先级反转(后者居上) 公平锁为了保证线程申请顺序,势必要付出一定的性能代价,因此其吞…...
C++中的 cout 和 printf 用法
文章目录 前言cout & printfexampleprintf输出string字符串总结 前言 C是一种面向对象的编程语言,它继承了C语言的特点,同时也增加了许多新的特性。在C中的cout 和 printf是两种常用的输出函数,它们都可以将数据显示在屏幕上,…...

Maven基础使用
Maven 学习目标 理解Maven的用途掌握Maven的基本操作掌握Maven如何创建Web项目 Maven是什么 面临问题 在学习Maven之前,我们先来看一下我们现在做的项目都有哪些问题。假设你现在做了一个crm的系统,项目中肯定要用到一些jar包,比如说myb…...

【C++ 入坑指南】(06)运算符
文章目录 一、算术运算符二、赋值运算符三、比较运算符四、逻辑运算符五、算法题5.1、拆分位数 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号。C 内置了丰富的运算符,并提供了以下类型的运算符: 运算符类型作用算术运算符用于处理四则运算赋值…...
了解一下js中的函数式编程
js中的函数式编程是一种编程范式,它将函数作为一等公民来使用。 在函数式编程中,函数是一种特殊的对象,可以赋值给变量、作为参数传递给其他函数、或作为其他函数的返回值。 函数式编程强调了函数的纯函数性,即函数输入相同时&a…...
动态HTTP代理在linux里的使用
动态HTTP代理是一种可以自动切换代理IP地址的代理方式,可以有效地绕过一些限制访问的网站。在Linux系统中,可以使用Privoxy和Proxychains来实现动态HTTP代理。 以下是在Linux中使用动态HTTP代理的步骤: 1. 安装Privoxy和Proxychains 在终端中…...
软考证书值得考吗?怎么考?
软考证书是什么?有什么用处?必须先明确这两个问题,才能有复习和考取的动力。怎么考过?这是第二步要着重解决的问题。今天详细帮助大家分析一下。 软考是国家级考试,具有强大的权威性与公信力。 软考全称为计算机技术…...
【win | 自动更新关闭】win11
利用本地组策略编辑器 对于Windows 11专业版或更高版本的用户,可以利用本地组策略编辑器来完全关闭自动更新。按下“WinR”键,输入“gpedit.msc”并回车。在本地组策略编辑器中,依次展开“计算机配置”>“管理模板”>“Windows组件”&…...
移除元素-JavaScript【算法学习day.04】
题目链接:27. 移除元素 - 力扣(LeetCode) 第一种思路 标签:拷贝覆盖 主要思路是遍历数组 nums,每次取出的数字变量为 num,同时设置一个下标 ans 在遍历过程中如果出现数字与需要移除的值不相同时ÿ…...

每日Prompt:双重曝光
提示词 新中式,这幅图像将人体头像轮廓与山水中式建筑融为一体,双重曝光,体现了反思、内心平静以及人与自然相互联系的主题,靛蓝,水墨画,晕染,极简...
【CSS-4】掌握CSS文字样式:从基础到高级技巧
文字是网页内容的核心载体,良好的文字样式设计不仅能提升可读性,还能增强网站的整体视觉效果。本文将全面介绍CSS中控制文字样式的各种属性和技巧,帮助您打造专业级的网页排版。 1. 基础文字属性 1.1 字体设置 (font-family) body {font-f…...

【评测】用Flux的图片文本修改的PS效果
【评测】Flux的图片文本修改的PS效果 1. 百度图库找一张有英文的图片 2. 打开https://playground.bfl.ai/image/edit上传图片 3. 输入提示词 “change brarfant to goodbeer” 图片的文字被修改了...

Kafka 入门指南与一键部署
Kafka 介绍 想象一下你正在运营一个大型电商平台,每秒都有成千上万的用户浏览商品、下单、支付,同时后台系统还在记录用户行为、更新库存、处理物流信息。这些海量、持续产生的数据就像奔腾不息的河流,你需要一个强大、可靠且实时的系统来接…...

沙市区举办资本市场赋能培训会 点赋科技分享智能消费新实践
荆州市沙市区,2025年6月5日—— 在沙市区政府主办的“发挥区域性股权市场功能,助力企业拥抱资本市场”专题培训会上,区委副书记、区长郭熙胜强调要充分发挥资本市场服务实体经济功能,推动本土创新企业高质量发展。区内重点企业点赋…...
【Linux内核】设备模型之udev技术详解
目录 1. udev技术概述 2. 技术层次分析 2.1 内核层交互 2.2 规则引擎层 2.3 用户空间实现 3. 关键技术要点 3.1 动态设备节点管理 3.2 热插拔处理 3.3 模块化规则系统 3.3.1. 变量替换功能 3.3.2. 条件判断能力 3.3.3. 实现机制 3.3.4 应用场景 3.3.5 扩展能力 4…...

怎么让大语言模型(LLMs)自动生成和优化提示词:APE
怎么让大语言模型(LLMs)自动生成和优化提示词:APE https://arxiv.org/pdf/2211.01910 1. 研究目标:让机器自己学会设计提示词 问题:大语言模型(如GPT-3)很强大,但需要精心设计的“提示词”才能发挥最佳效果。过去靠人工设计提示词,费时费力,还可能因表述差异导致模…...

AI Infra运维实践:DeepSeek部署运维中的软硬结合
发布会资料 《AI Infra运维实践:DeepSeek部署运维中的软硬结合》 袋鼠云运维服务 1、行业痛点 随着数字化转型的深入,企业面临的运维挑战日益复杂,所依托的平台在长期使用的过程中积累了各式各样的问题或者难点。这些问题不仅影响效率&…...