线程池ThreadPoolExecutor使用指南

在这里插入图片描述

线程池ThreadPoolExecutor使用指南

🧐使用线程池的好处是什么?

统一管理,减少资源获取创建的开销,提高利用率。

🔧线程池的参数

ThreadPoolExecutor​ 3 个最重要的参数:

  • corePoolSize​ : 任务队列未达到队列容量时,最大可以同时运行的线程数量。

  • maximumPoolSize​ : 任务队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。

  • workQueue​: 新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中

ThreadPoolExecutor​其他常见参数 :

  • keepAliveTime​:线程池中的线程数量大于 corePoolSize​ 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime​才会被回收销毁。
  • unit​ : keepAliveTime​ 参数的时间单位。
  • threadFactory​ :executor 创建新线程的时候会用到。
  • handler​ :拒绝策略
🤔你是如何创建线程池的?为什么不建议直接用Executors​创建线程池?

一般不建议直接用Executors​创建线程池的,这种方式缓冲队列没有限制合适的大小(默认整形的最大值),处理不好会有OOM的风险。而是通过 ThreadPoolExecutor​ 构造函数的方式,这样的好处就是更加明确线程池的运行规则,规避资源耗尽的风险。

    public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());}
    public LinkedBlockingQueue() {this(Integer.MAX_VALUE);}
✨线程池的策略有哪些?

当前同时运行的线程数量达到最大线程数量并且队列也已经被放满了任务时:

常见的策略有拒绝策略:

  • AbortPolicy​ 抛出 RejectedExecutionException​来拒绝新任务的处理。

  • CallerRunsPolicy​:调用执行自己的线程运行任务,由主线程自己来执行这个任务。(不允许丢弃任务适合该策略)

不常见策略(了解既可):

  • ThreadPoolExecutor.DiscardPolicy​:不处理新任务,直接丢弃掉。
  • ThreadPoolExecutor.DiscardOldestPolicy​:此策略将丢弃最早的未处理的任务请求。
📌Springboot下使用示例

当您使用ThreadPoolTaskExecutor​配置线程池时,可以参考以下示例代码:

ThreadPoolConfig​类通过@Configuration​注解标记为配置类,并定义了一个名为taskExecutor​的Bean,类型为ThreadPoolTaskExecutor​。在taskExecutor()​方法中,设置了线程池的核心线程数为10,最大线程数为20,队列容量为30,线程名前缀为"MyThread-",然后调用initialize()​方法初始化线程池,并返回配置好的ThreadPoolTaskExecutor​实例

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configuration
public class ThreadPoolConfig {@Beanpublic ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10); // 设置核心线程数executor.setMaxPoolSize(20); // 设置最大线程数executor.setQueueCapacity(30); // 设置队列容量executor.setThreadNamePrefix("MyThread-"); // 设置线程名前缀executor.initialize(); // 初始化线程池return executor;}
}

异步任务的地方注入TaskExecutor Bean,并调用其execute()方法来提交任务:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;@Service
public class MyService {@Autowiredprivate ThreadPoolTaskExecutor taskExecutor;public void executeAsyncTask() {taskExecutor.execute(() -> {// 执行异步任务的逻辑System.out.println("Async task executed by thread: " + Thread.currentThread().getName());});}
}

然而,也有一些特殊场景下可能需要手动创建线程池实例:

  1. 定制化需求:如果需要对线程池进行高度定制,例如设置特定的线程池参数或使用特殊的线程工厂等,可能需要手动创建线程池实例。
  2. 独立使用:某些情况下,线程池只在一个特定的类或模块中使用,并且不需要在整个应用中共享,这时候手动创建线程池可能更合适。

大多数情况下建议将线程池实例交给Spring容器管理,以便统一管理和便于集成;如果手动创建了线程池实例,建议在某个特定的时机手动调用线程池的shutdown()​方法来优雅地关闭线程池,释放资源。

但这个特定时机怎么定义?使用CountDownLatch​或许可以符合你的场景。

CountDownLatch​的使用

CountDownLatch​ 的作用就是 允许 多个线程阻塞在一个地方,直到所有线程的任务都执行完毕。那么手动创建的线程就可以通过shutdown()​方法来优雅地关闭线程池了。

package com.fjh.demo.thread;import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/*** @ClassName: CustomThreadPoolExample* @Description: TODO 手动自定义创建线程池,CountDownLatch使用场景* @Author: fengjiahao* @Date: 2024/6/15 21:26*/
public class CustomThreadPoolExample {public static void main(String[] args) throws InterruptedException {int numThreads = 5;// 核心线程数int corePoolSize = 3;// 最大线程数int maxPoolSize = 5;// 线程空闲时间long keepAliveTime = 10;// 任务队列,使用有界队列ArrayBlockingQueueThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, // 核心线程数maxPoolSize, // 最大线程数keepAliveTime, // 线程空闲时间TimeUnit.SECONDS, // 时间单位new ArrayBlockingQueue<>(3) // 任务队列);CountDownLatch latch = new CountDownLatch(numThreads);for (int i = 0; i < numThreads; i++) {int finalI = i;executor.execute(() -> {try {System.out.println("Thread【"+ finalI +"】 started execute: " + Thread.currentThread().getName());Thread.sleep(2000); // 模拟线程执行任务} catch (InterruptedException e) {e.printStackTrace();}finally{latch.countDown(); // 每个线程执行完成后调用countDown方法}System.out.println("Thread finished: " + Thread.currentThread().getName());});}latch.await(); // 等待所有线程执行完成System.out.println("All threads have finished. Continuing main thread.");executor.shutdown(); // 关闭线程池}
}
☕最后

其实java8中有更加优雅的方式处理这种场景CompletableFuture​,有兴趣的同学可以去了解下🙂

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

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

相关文章

docker login 报错: http: server gave HTTP response to HTTPS client

环境&#xff1a; 自建 Harbor、Docker 1. 问题分析 # 命令&#xff0c;这里用的是 IP&#xff0c;可以为域名 docker login -u test 172.16.51.182:31120 # 输入密码 Password:# 报错如下&#xff1a; Error response from daemon: Get "https://172.16.51.182:31120/…

[Algorithm][贪心][增减字符串匹配][分发饼干][最优除法][跳跃游戏Ⅱ][跳跃游戏]详细讲解

目录 1.增减字符串匹配1.题目链接2.算法原理详解3.代码实现 2.分发饼干1.题目链接2.算法原理详解3.代码实现 3.最优除法1.题目链接2.算法原理详解3.代码实现 4.跳跃游戏 II1.题目链接2.算法原理详解3.代码实现 5.跳跃游戏1.题目链接2.算法原理详解3.代码实现 1.增减字符串匹配 …

期末复习6--链表头插法(逆序)尾插法(顺序)---输出链表

头插法 #include <stdio.h> #include <stdlib.h>struct Node //定义结构体 {char data; //数据域struct Node * next; //指针域 };/* 请在这里填写答案 */void PrintList (struct Node * head) {struct Node * s;if(head NULL){printf("None&qu…

Apipost模拟HTTP客户端

模拟HTTP客户端的软件有很多&#xff0c;其中比较著名的就有API-FOX、POSTMAN。 相信很多小伙伴都使用POSTMAN。这篇博客主要介绍Apipost的原因是&#xff0c;Apipost无需下载&#xff0c;具有网页版。 APIFOX的站内下载&#xff1a; Api-Fox&#xff0c;类似于PostMan的软件…

JavaFX 节点

JavaFX Node类javafx.scene.Node是添加到JavaFX 场景图的所有组件 的基类&#xff08;超类&#xff09; 。JavaFX Node 类是抽象的&#xff0c;因此你只需将 Node 类的子类添加到场景图中。场景图中的所有 JavaFX Node 实例共享一组由 JavaFX Node 类定义的公共属性。本 JavaFX…

一文了解Redis

一.什么是Redis 与MySQL一样&#xff0c;Redis也是客户端服务器结构的程序&#xff0c;是基于内存的键值对存储系统&#xff0c;属于NoSQL的一种。与很多键值对数据库不同的是&#xff0c;Redis 中的值可以是由 string&#xff08;字符串&#xff09;、hash&#xff08;哈希&a…

【算法专题--链表】删除排序链表中的重复元素II -- 高频面试题(图文详解,小白一看就懂!!)

目录 一、前言 二、题目描述 三、解题方法 ⭐ 双指针 -- 采用 哨兵位头节点 &#x1f95d; 什么是哨兵位头节点&#xff1f; &#x1f34d; 解题思路 &#x1f34d; 案例图解 四、总结与提炼 五、共勉 一、前言 删除排序链表中的重复元素II元素这道题&#xff0c…

【JKI SMO】框架讲解(二)

JKI State Machine 讲解 将JKI State Machine 模板拖曳到程序框图中&#xff0c; 如下图&#xff0c; 此模板会默认放置一个OK按钮在前面板中&#xff0c;用于提示用户如何增加一个简单的用户事件去使用此框架。 “Event Structure”&#xff0c;Idle&#xff1a;此分支可以设…

【JS重点17】原型链(面试重点)

一&#xff1a;原型链底层原理 以下面一段代码为例&#xff0c;基于原型对象&#xff08;Star构造函数的原型对象&#xff09;的继承使得不同构造函数的原型对象关联在一起&#xff08;此处是最大的构造函数Object原型对象&#xff09;&#xff0c;并且这种关联的关系是一种链…

C#联合Halcon机器视觉框架源码—升级版

相较于之前的NxtVision&#xff0c;本软件代码架构更加合理&#xff0c;且新增ui设计器、原来的vb脚本改为C#脚本&#xff0c;并尝试将视觉与运动控制相结合&#xff0c;是一体化的框架。 对源码有需求的&#xff0c;订阅本专栏后&#xff0c;私信我领取。

活动集锦 | 英码科技积极参与行业盛会,AI赋能城市数字化转型

在当今数字经济时代&#xff0c;城市全域数字化转型已经成为提升城市管理效能、优化资源配置、推动经济发展的重要手段。英码科技始终致力于为企业打造高效、低成本的行业应用方案&#xff0c;助力企业实现数字化转型。近日&#xff0c;英码科技受邀参加了多场行业展示活动&…

操作系统复习-线程同步

互斥量 两个线程的指令交叉执行互斥量可以保证先后执行称为原子性 原子性是指一系列操作不可被中断的特性这一系列操作要么全部执行完成&#xff0c;要么全部没有执行不存在部分执行部分未执行的情况 互斥锁 互斥量是最简单的线程同步的方法互斥锁&#xff0c;处于两态之一的…

01 飞行器设计 —— 一门独立的学科

01 飞行器设计 —— 一门独立的学科 01 引言02 飞机设计概述2-1 什么是飞机设计&#xff1f;2-1 飞机设计是从哪里开始的&#xff1f;2-2 如何成为一名飞机设计师&#xff1f;2-4 本书的组织 参考文献 说明&#xff1a;关于Raymer的《Aircraft Design》的读书笔记&#xff1b; …

解读ROS功能包模块的步骤

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言解读ROS功能包模块的步骤前言 认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长! 推荐开发经验及方法博客专栏: [https:/…

哇塞,超好吃的麻辣片,一口就爱上

最近&#xff0c;我发现了一款让人欲罢不能的美食——食家巷麻辣片&#xff01;&#x1f60d; 一打开包装&#xff0c;那浓郁的麻辣香气就扑鼻而来&#xff0c;瞬间刺激着我的嗅觉神经。&#x1f603;食家巷麻辣片的外观色泽鲜艳&#xff0c;红通通的一片&#xff0c;看着就特…

Android断点续传原理及实现

常见两种网络请求方式 一、 HttpURLConnection HttpURLConnection的setRequestProperty()方法&#xff0c;对我们要读取的字节部分进行控制&#xff0c;比如: 1.Range0-100代表只读取前100个字节。 2.Range100-500代表读取从第100个字节开始&#xff0c;读到第500个字节为止。…

常见的宽基指数基金

指数基金投资指南 ❝ 这篇博客里面的内容主要来自于银行螺丝钉的《定投十年&#xff0c;财务自由》和《指数基金投资指南》这两本书中章“常见的宽基指数”&#xff0c;最近第三次读这本书&#xff0c;打算做一点笔记加深自己的印象。 博客中很多内容是从书中摘抄的&#xff0c…

【git使用三】git工作机制与命令用法

目录 git工作机制和相关概念 四个重要区域 分支的概念 上传代码到远程分支的基本流程 克隆代码 仓库同步 开发者如何提交代码到远程仓库分支 1.初始化本地仓库 2.关联本地仓库和远程仓库 创建关联 查看关联情况 如何解除关联 3.推送代码到远程仓库 3.1先下拉远程…

PyTorch计算机视觉入门:测试模型与评估,对单帧图片进行推理

在完成模型的训练之后&#xff0c;对模型进行测试与评估是至关重要的一步&#xff0c;它能帮助我们理解模型在未知数据上的泛化能力。本篇指南将带您了解如何使用PyTorch进行模型测试&#xff0c;并对测试结果进行分析。我们将基于之前训练好的模型&#xff0c;演示如何加载数据…

解决老毛子路由器自带微信提示功能无法触发问题

新买了一个二手的RM AC2100&#xff0c;刷了老毛子后&#xff0c;发现自带的上下线微信提示无法使用(方糖公众号无信息) 经我开启SSH&#xff0c;将上下线部分代码拿出来调试发现&#xff0c;发不出来的原因是原版信息发送长度过长&#xff0c;需要截取一部分才能发送成功。 …