当前位置: 首页 > news >正文

JUC的线程池架构

🙈作者简介:练习时长两年半的Java up主
🙉个人主页:程序员老茶
🙊 ps:点赞👍是免费的,却可以让写博客的作者开心好久好久😎
📚系列专栏:Java全栈,计算机系列(火速更新中)
💭 格言:种一棵树最好的时间是十年前,其次是现在
🏡动动小手,点个关注不迷路,感谢宝子们一键三连

目录

  • 课程名:Java
    • 内容/作用:知识点/设计/实验/作业/练习
    • 学习:JUC的线程池架构
  • JUC的线程池架构
    • 一、线程池的基本概念
    • 二、线程池的使用方法
      • 1. 创建线程池
      • 2. 提交任务到线程池
      • 3. 关闭线程池
    • 三、线程池的核心组件
      • 1. ThreadPoolExecutor
      • 2. BlockingQueue
      • 3. 拒绝策略
    • 四、自定义线程池示例
      • 1. 创建自定义线程池
      • 2. 使用自定义线程池

课程名:Java

内容/作用:知识点/设计/实验/作业/练习

学习:JUC的线程池架构

JUC的线程池架构

本文主要介绍Java中如何使用java.util.concurrent包中的线程池(ExecutorServiceThreadPoolExecutor)来实现高并发、高可用的系统。我们将从线程池的基本概念、使用方法、核心组件以及自定义线程池四个方面进行阐述。

一、线程池的基本概念

线程池是一种管理线程的机制,它可以有效地控制线程的数量,避免大量线程之间的切换导致性能下降。线程池中的线程可以被复用,当一个任务完成后,线程不会被销毁,而是被重新分配给新的任务。

二、线程池的使用方法

1. 创建线程池

在Java中,可以通过Executors工具类来创建不同类型的线程池。例如,创建一个固定大小的线程池:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolDemo {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(5);}
}

2. 提交任务到线程池

使用submit()方法将任务提交到线程池中执行:

executorService.submit(new Runnable() {@Overridepublic void run() {System.out.println("任务执行中...");}
});

3. 关闭线程池

当所有任务都执行完毕后,需要关闭线程池以释放资源:

executorService.shutdown();

三、线程池的核心组件

1. ThreadPoolExecutor

ThreadPoolExecutorExecutorService接口的实现类,它提供了更多的功能,如定时执行、定期执行、异常处理等。我们通常需要自己实现一个ThreadPoolExecutor来满足业务需求。

2. BlockingQueue

BlockingQueue是一个阻塞队列,用于存放待处理的任务。它是一个FIFO(先进先出)的队列,当队列满时,新来的任务会等待;当队列为空时,正在执行的任务会等待。常用的阻塞队列有ArrayBlockingQueueLinkedBlockingQueueSynchronousQueue

3. 拒绝策略

当线程池无法处理新提交的任务时,需要采取一定的策略来处理这些任务。Java中的RejectedExecutionHandler接口提供了四种默认的拒绝策略:

  1. CallerRunsPolicy:直接在调用者线程中运行任务。
  2. AbortPolicy:抛出一个未检查异常中断任务。
  3. DiscardPolicy:丢弃任务,不做任何处理。
  4. DiscardOldestPolicy:丢弃队列中最旧的任务,尝试重新提交新任务。

我们可以根据实际需求自定义拒绝策略。例如,下面是一个自定义的拒绝策略示例:

import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {private static final int MAX_CAPACITY = 100; // 最大容量private AtomicInteger rejectedCount = new AtomicInteger(); // 被拒绝的任务计数器private ArrayBlockingQueue<Runnable> taskQueue; // 任务队列public CustomRejectedExecutionHandler() {taskQueue = new ArrayBlockingQueue<>(MAX_CAPACITY); // 初始化任务队列}@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 拒绝策略实现方法if (taskQueue.remainingCapacity() == 0) { // 如果队列已满,添加拒绝策略executor.setRejectedExecutionHandler(new RejectedExecutionHandler() { // 设置新的拒绝策略@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { // 拒绝策略实现方法(AbortPolicy)System.err.println("Task queue is full, rejecting task: " + r); // 输出错误信息并抛出异常(AbortPolicy)throw new RejectedExecutionException("Task queue is full", r); // 抛出RejectedExecutionException异常(AbortPolicy)}});} else { // 如果队列未满,将任务添加到队列中,并增加计数器(CallerRunsPolicy)或直接抛出异常(DiscardPolicy/DiscardOldestPolicy)taskQueue.put(r); // 将任务添加到队列中(非阻塞)rejectedCount.incrementAndGet(); // 被拒绝的任务计数器加1(CallerRunsPolicy/DiscardPolicy/DiscardOldestPolicy)或直接抛出异常(DiscardPolicy/DiscardOldestPolicy)}}
}

四、自定义线程池示例

下面我们通过一个示例来说明如何自定义线程池:假设我们需要一个支持定时执行和周期性执行的任务线程池,我们可以这样实现:
要实现一个支持定时执行和周期性执行的任务线程池,我们可以创建一个自定义的线程池类,继承自ThreadPoolExecutor,并重写其中的方法。以下是一个简单的示例:

import java.util.concurrent.*;public class CustomThreadPoolExecutor extends ThreadPoolExecutor {private final long keepAliveTime;private final TimeUnit unit;public CustomThreadPoolExecutor(int corePoolSize, long keepAliveTime, TimeUnit unit) {super(corePoolSize);this.keepAliveTime = keepAliveTime;this.unit = unit;}@Overrideprotected void beforeExecute(Thread t, Runnable r) {super.beforeExecute(t, r);// 在任务执行前执行的操作,例如记录日志、初始化资源等}@Overrideprotected void afterExecute(Runnable r, Throwable t) {super.afterExecute(r, t);// 在任务执行后执行的操作,例如清理资源、记录日志等}public void scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {super.scheduleAtFixedRate(command, initialDelay, period, unit);}public void scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {super.scheduleWithFixedDelay(command, initialDelay, delay, unit);}
}

在这个示例中,我们创建了一个名为CustomThreadPoolExecutor的自定义线程池类,它继承自ThreadPoolExecutor。我们为这个类添加了两个方法:scheduleAtFixedRatescheduleWithFixedDelay,分别用于定时执行和周期性执行任务。这两个方法内部调用了父类的相应方法来实现任务调度。

使用这个自定义线程池的示例代码如下:

import java.util.concurrent.*;public class CustomThreadPoolExample {public static void main(String[] args) throws InterruptedException {CustomThreadPoolExecutor threadPool = new CustomThreadPoolExecutor(2, 10, TimeUnit.SECONDS);for (int i = 0; i < 5; i++) {final int taskId = i;threadPool.execute(() -> {System.out.println("Task " + taskId + " is running");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Task " + taskId + " is completed");});}// 关闭线程池(所有任务执行完成后,线程池不再接受新任务)threadPool.shutdown();}
}

在这个示例中,我们创建了一个定时执行任务的线程池,核心线程数为2,任务间隔时间为10秒。然后,我们提交了5个任务到线程池,每个任务打印一条开始和结束信息,并在运行过程中暂停1秒。由于线程池具有定时执行功能,因此这些任务会按照设定的时间间隔依次执行。最后,我们在所有任务执行完成后关闭线程池。

在Java中,我们可以通过java.util.concurrent.Executors类创建线程池。然而,有时候我们需要创建一个具有特定功能的线程池,例如定时执行任务、周期性执行任务等。这时,我们可以创建一个自定义的线程池来实现这些功能。本文将介绍如何创建一个自定义线程池,并通过一个示例来演示其使用方法。

1. 创建自定义线程池

要创建一个自定义线程池,我们需要实现java.util.concurrent.ThreadPoolExecutor接口,并重写其中的方法。以下是一个简单的自定义线程池实现:

import java.util.concurrent.*;public class CustomThreadPoolExecutor extends ThreadPoolExecutor {private final int corePoolSize;private final BlockingQueue<Runnable> workQueue;private final long keepAliveTime;private final TimeUnit unit;public CustomThreadPoolExecutor(int corePoolSize, BlockingQueue<Runnable> workQueue, long keepAliveTime, TimeUnit unit) {this.corePoolSize = corePoolSize;this.workQueue = workQueue;this.keepAliveTime = keepAliveTime;this.unit = unit;}@Overrideprotected void beforeExecute(Thread t, Runnable r) {super.beforeExecute(t, r);// 在任务执行前执行的操作,例如记录日志、初始化资源等}@Overrideprotected void afterExecute(Runnable r, Throwable t) {super.afterExecute(r, t);// 在任务执行后执行的操作,例如清理资源、记录日志等}
}

2. 使用自定义线程池

创建好自定义线程池后,我们可以像使用普通的ThreadPoolExecutor一样使用它。以下是一个使用自定义线程池的示例:

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;public class CustomThreadPoolExample {public static void main(String[] args) {// 创建一个定时执行任务的线程池CustomThreadPoolExecutor threadPool = new CustomThreadPoolExecutor(2, new LinkedBlockingQueue<>(2), 30, TimeUnit.SECONDS);// 提交任务到线程池for (int i = 0; i < 5; i++) {final int taskId = i;threadPool.execute(() -> {System.out.println("Task " + taskId + " is running");try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Task " + taskId + " is completed");});}// 关闭线程池(所有任务执行完成后,线程池不再接受新任务)threadPool.shutdown();}
}

在这个示例中,我们创建了一个定时执行任务的线程池,最大容量为2,任务队列大小为2,空闲线程的存活时间为30秒。然后,我们提交了5个任务到线程池,每个任务打印一条开始和结束信息,并在运行过程中暂停1秒。由于线程池具有定时执行功能,因此这些任务会按照设定的时间间隔依次执行。最后,我们在所有任务执行完成后关闭线程池。

往期专栏
Java全栈开发
数据结构与算法
计算机组成原理
操作系统
数据库系统
物联网控制原理与技术

相关文章:

JUC的线程池架构

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;…...

PostgreSQL limit 语法

PostgreSQL limit 语法 LIMIT 是 PostgreSQL 中用于限制查询结果数量的关键字。其语法如下&#xff1a; SELECT column1, column2, ... FROM table_name LIMIT number_of_rows;其中&#xff0c;SELECT 语句用于指定要查询的列和数据表&#xff0c;LIMIT 用于指定查询结果的行…...

CUDA C编程权威指南:2.1-CUDA编程模型

本文主要通过例子介绍了CUDA异构编程模型&#xff0c;需要说明的是Grid、Block和Thread都是逻辑结构&#xff0c;不是物理结构。实现例子代码参考文献[2]&#xff0c;只需要把相应章节对应的CMakeLists.txt文件拷贝到CMake项目根目录下面即可运行。 1.Grid、Block和Thread间的…...

两条记录合并成一条记录

两条记录合并成一条记录 两条记录 val4,type_idlevel 和 val6,type_idtypeId 合并成一条记录 level4,typeId6 可以使用 条件聚合语句 CASE WHEN … 和 MAX 函数来实现。假设有以下 my_table 表&#xff1a; --------------------- | id | val | type_id | --------------…...

vue3 + typescript + vite + naive ui + tailwindcss + jsx 仿苹果桌面系统

基于 vue3.x typescript vite naive ui tailwindcss jsx vue-router pinia&#xff0c;项目使用 tsx 作为模版输出&#xff0c;全程没有使用vue提供的SFC&#xff0c; 仿macos桌面前端项目&#xff0c;开源免费模版&#xff0c;希望减少工作量和学习新技术&#xff0c;希…...

揭秘,用软件一秒识别纸质表格数字,找到你想要的一串数字

要将纸质表格的数字快速用软件识别并找出特定的一串数字&#xff0c;以下是三种常用的方案&#xff1a; 方案一&#xff1a;使用OCR软件识别和搜索功能 1. 扫描纸质表格并保存为图像或PDF格式。 2. 使用OCR&#xff08;光学字符识别&#xff09;软件&#xff0c;如金鸣表格文字…...

解析图片文件格式

图片文件幻数 关于JPEG格式 二进制形式打开文件&#xff0c;文件开始字节为FF D8&#xff0c;文件结束两字节为FF D9 JPEG 文件有两种不同的元数据格式&#xff1a;JFIF 和 EXIF。 JFIF 以 ff d8 ff e0 开头&#xff0c;EXIF 以 ff d8 ff e1 开头。 代码示例 private static…...

新的“HTTP/2 快速重置”零日攻击打破了 DDoS 记录

自 8 月份以来&#xff0c;一种名为“HTTP/2 快速重置”的新 DDoS&#xff08;分布式拒绝服务&#xff09;技术已被作为零日漏洞积极利用&#xff0c;其规模打破了之前的所有记录。 Amazon Web Services、Cloudflare 和 Google 今天联合发布了有关零日技术的消息&#xff0c;他…...

现代化战机之路:美国空军U-2侦察机基于Jenkins和k8s的CI/CD架构演进

▲ 点击上方"DevOps和k8s全栈技术"关注公众 华为北京研究所Q27大楼 随着技术的不断进步&#xff0c;军事领域也在积极采纳现代化工具来提高战备水平和效率。美国空军的U-2侦察机项目是一个鲜明的例子&#xff0c;它成功地借助Jenkins和Kubernetes&#xff08;k8s&…...

Linux中常用的软件:Squid

在Linux系统中&#xff0c;有许多不同的代理软件可供选择。本文将比较两个常用的代理软件&#xff1a; Squid。我们将介绍它们的特点、使用场景和优缺点&#xff0c;帮助您选择适合自己需求的代理软件。 - 支持多种加密协议&#xff0c;包括AES、ChaCha20和RC4等&#xff0c;可…...

Ali MaxCompute SDK

ALI MC 文件读写 public abstract BufferedInputStream readResourceFileAsStream(String var1) throws IOException;LocalExecutionContext.java Overridepublic BufferedInputStream readResourceFileAsStream(String resourceName) throws IOException {try {return wareHou…...

解决element中table在页面切换时候表格底部出现空白

activated(){ this.$refs.table.doLayout() } activated()是Vue中一个很重要的生命周期函数&#xff0c;它是在组件大概率会被复用时调用的。当组件被复用时&#xff0c;原来的组件的数据和状态必须得到保留。activated()函数能够保持组件在别处被活化时的状态数据。 activat…...

Vue中对路由的进阶学习

路由进阶 文章目录 路由进阶1、路由的封装抽离2、声明式导航2.1、导航链接2.2、高亮类名2.3、跳转传参2.4、动态路由参数可选符 3、Vue路由--重定向4、Vue路由--4045、Vue路由–模式设置6、编程式导航6.1、基本跳转6.2、跳转传参 路由基础入门 1、路由的封装抽离 问题&#x…...

Vuex的同步存值与取值及异步请求

前言 1.概念 Vuex是一个用于管理Vue.js应用程序中状态的状态管理模式和库。Vue.js是一个流行的JavaScript框架&#xff0c;用于构建用户界面&#xff0c;而Vuex则专门用于管理应用程序的状态&#xff0c;以确保状态在整个应用程序中保持一致和可维护。 2.Vuex的特点&#xf…...

【Python爬虫 js渲染思路一】

Python爬虫 破解js渲染思路一 当我们在谈论网页js渲染的时候&#xff0c;我们在谈论什么 js渲染网页&#xff0c;从某种程度来说&#xff0c;是指单纯的http请求&#xff0c;返回的文本数据&#xff0c;与我们在浏览器看到的内容&#xff0c;相距甚远.其可包括为以下几点&…...

智慧安防AI视频智能分析云平台EasyCVR加密机授权小tips

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发、视频集中存储等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、…...

C# Windows 窗体控件中的边距和填充

可以将 Margin 属性、Left、Top、Right、Bottom 的每个方面设置为不同的值&#xff0c;也可以使用 All 属性将它们全部设置为相同的值。 在代码中设置Margin&#xff0c;元素的左边设置为5个单位、上边设置为10个单位、右边设置为15个单位和下边设置为20个单位。 TextBox myT…...

腾讯云2核4G轻量服务器5M带宽支持多少人同时在线?

腾讯云轻量2核4G5M带宽服务器支持多少人在线访问&#xff1f;5M带宽下载速度峰值可达640KB/秒&#xff0c;阿腾云以搭建网站为例&#xff0c;假设优化后平均大小为60KB&#xff0c;则5M带宽可支撑10个用户同时在1秒内打开网站&#xff0c;从CPU内存的角度&#xff0c;网站程序效…...

01 初识FPGA

01 初识FPGA 一.FPGA是什么 FPGA&#xff08;Filed Programmable Gate Array&#xff09;&#xff0c;现场可编程门阵列&#xff0c;一种以数字电路为主的集成芯片&#xff0c;属于可编程逻辑器件PLD的一种。 1.1 两大巨头 Xilinx(赛灵思)Altera&#xff08;阿尔特拉&#…...

设备巡检管理系统与隐患排查治理

如何才能将设备巡检做细做规范呢&#xff1f; 1.制定巡检制度和流程&#xff1a;通过建立明确的巡检制度和流程&#xff0c;并将其纳入企业的安全管理体系中。利用凡尔码平台制定一个详细的巡检计划&#xff0c;包括巡检的时间、地点、内容、检查方法和注意事项等&#xff0c;帮…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...