线程池的简单实现与应用

1.什么是线程池 

线程池其实就是一种多线程处理形式,处理过程中可以将任务添加到队列中,然后在创建线程后自动启动这些任务。

线程池最大的好处就是减少每次启动、销毁线程的损耗。

2.线程池参数介绍 

参数名称说明
corePoolSize正式员工的数量.(正式员工,一旦录用,永不辞退,干活的主力)
maximumPoolSize

正式员工+临时工的数目.(临时工:活多了,正式员工干不完,就招临时工干活,活不多的时候就裁掉)

也就是说核心线程不忙的时候,非核心线程就会被回收

keepAliveTime临时工允许的空闲时间
unitkeepaliveTime的时间单位,是秒,分钟,还是其他值.
workQueue传递任务的阻塞队列
threadFactory创建线程的工厂,参与具体的创建线程工作.通过不同线程工厂创建出的线程相当于对⼀些属性进⾏了不同的初始化设置
RejectedExecutionHandler拒绝策略,如果任务量超出公司的负荷了接下来怎么处理.

 RejectedExecutionHandler

  • AbortPolicy():超过负荷,直接抛出异常.(让程序员知道任务太多了,处理不过来,代码罢工)
  • CallerRunsPolicy():调用者负责处理多出来的任务.(线程池满了,多出来的任务自己处理)
  • DiscardOldestPolicy():丢弃队列中最老的任务.(这样新的任务可以排进队列里)
  • DiscardPolicy():丢弃新来的任务,按照原有的节奏进行
     

 3.使用Executors 创建常见的线程池

 Executors创建线程池的几种方式:

  • newFixedThreadPool:创建固定线程数的线程池
  • newCachedThreadPool:创建线程数目动态增⻓的线程池.
  • newSingleThreadExecutor:创建只包含单个线程的线程池.
  • newScheduledThreadPool:设定延迟时间后执行命令,或者定期执行命令.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class Demo34 {public static void main(String[] args) {//                能够根据任务的数目, 自动进行线程扩容.
//                Executors.newCachedThreadPool();
//                创建固定线程数目的线程池.
//                Executors.newFixedThreadPool(10);
//                创建一个只包含单个线程的线程池.
//                Executors.newSingleThreadExecutor();
//                创建一个固定线程个数, 但是任务延时执行的线程池.
//                Executors.newScheduledThreadPool(10);// 创建固定线程数目的线程池.//ExecutorService service = Executors.newFixedThreadPool(10);// 能够根据任务的数目, 自动进行线程扩容.//ExecutorService service=Executors.newCachedThreadPool();//创建一个只包含单个线程的线程池.//ExecutorService service=Executors.newSingleThreadExecutor();//创建一个固定线程个数, 但是任务延时执行的线程池.ExecutorService service=Executors.newScheduledThreadPool(10);for (int i = 0; i < 1000; i++) {int id = i;service.submit(new Runnable() {@Overridepublic void run() {System.out.println("tjctsl" + id + ", " + Thread.currentThread().getName());}});}}
}

 4.实现一个简单的线程池 


import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;class MyThreadPool {private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);private int maxPoolSize = 0;private List<Thread> threadList = new ArrayList<>();// 初始化线程池 (FixedThreadPool)public MyThreadPool(int corePoolSize, int maxPoolSize) {this.maxPoolSize = maxPoolSize;// 创建若干个线程for (int i = 0; i < corePoolSize; i++) {Thread t = new Thread(() -> {try {while (true) {Runnable runnable = queue.take();runnable.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();threadList.add(t);}}// 把任务添加到线程池中public void submit(Runnable runnable) throws InterruptedException {// 此处进行判定, 判定说当前任务队列的元素个数, 是否比较长.// 如果队列元素比较长, 说明已有的线程, 不太能处理过来了. 创建新的线程即可.// 如果队列不是很长, 没必要创建新的线程.queue.put(runnable);// 这里的 阈值 可以灵活调节if (queue.size() >= 500 && threadList.size() < maxPoolSize) {// 创建新的线程即可Thread t = new Thread(() -> {try {while (true) {Runnable task = queue.take();task.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();}}
}public class Demo35 {public static void main(String[] args) throws InterruptedException {MyThreadPool threadPool = new MyThreadPool(10, 20);for (int i = 0; i < 10000; i++) {int id = i;threadPool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello " + id + ", " + Thread.currentThread().getName());}});}}
}

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

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

相关文章

【软考】模拟考卷错题本2024-05-14

1 活动图-计算时间差 审题&#xff0c;第几天~选的3、10是结束了上一次的活动并未开始呢 &#xff01;所以记得按照正常的语序表达哦&#xff01; 2 队列-算长度 代入法&#xff0c;设计一个开始为0&#xff0c;结尾为9 &#xff0c;容量为10即M的队列&#xff1b;带入计算当前…

深入理解MySQL三大日志:redo log、binlog、undo log

前言 MySQL是一个功能强大的关系型数据库管理系统&#xff0c;它的高可靠性、高性能和易用性使得它成为众多企业和开发者的首选。在MySQL内部&#xff0c;为了保证数据的完整性、恢复能力和并发性能&#xff0c;设计了一套复杂的日志系统。其中&#xff0c;redo log、bin log和…

滑动窗口算法及相关习题

滑动窗口 又叫"同向双指针", left和right指针构成一个窗口 一般可以利用单调性时, 用到滑动窗口 使用: 定义left 0,right 0进窗口判断出窗口 还有一步是更新结果, 在哪一步更新是根据题意的 其中234步循环进行 一. 长度最小的子数组 答案 二.无重复字符的最长…

时间序列预测:探索性数据分析和特征工程的实用指南

时间序列分析是数据科学和机器学习领域最广泛的主题之一:无论是预测金融事件、能源消耗、产品销售还是股票市场趋势&#xff0c;这一领域一直是企业非常感兴趣的领域。 随着机器学习模型的不断进步&#xff0c;使除了传统的统计预测方法(如回归模型、ARIMA模型、指数平滑)外&a…

STM32快速入门(定时器之输入捕获)

STM32快速入门&#xff08;定时器之输入捕获&#xff09; 前言 本节主要讲解STM32利用通用定时器&#xff0c;在输入引脚出现指定电平跳变时&#xff0c;将CNT的值锁存到CCR寄存器当中&#xff0c;从而计算PWM波形的频率、占空比、脉冲间隔、电平持续时间等。其功能的应用有&…

力扣刷题 day2

快乐数 202. 快乐数 - 力扣&#xff08;LeetCode&#xff09;   图: java // 快乐数 --> 19 > 1^2 9 ^2 82 > 82 > 8 ^ 2 2 ^ 2 ......public boolean isHappy(int n) {// 使用快慢指针int slow n, fast getSum(n);while (slow ! fast) {slow getSum(slo…

Typora+PicGo+Gitee设置图床,解决CSDN上传markdown文件图片加载不出来的问题(超级实用)

注&#xff1a; 由于gitee现在已经加上了防盗链&#xff0c;并且只支持1M的图片&#xff0c;我觉得不是很好用&#xff08;可以买腾讯云或阿里云等&#xff09;&#xff0c;之后找到比较好点的图床工具也会持续更新的。&#xff08;sm.ms好像还好&#xff0c;github网速不太稳定…

十大排序算法之->归并排序

一、归并排序简介 归并排序是一种基于分治策略的有效且稳定的排序算法。归并排序由约翰冯诺伊曼提出&#xff0c;是计算机科学中一个非常基础且历史悠久的算法。 归并排序利用分治法的策略&#xff0c;将一个大的数组拆分成几个小的子数组&#xff0c;这些子数组各自独立地排…

每日两题 / 236. 二叉树的最近公共祖先 124. 二叉树中的最大路径和(LeetCode热题100)

236. 二叉树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; dfs统计根节点到p&#xff0c;q节点的路径&#xff0c;两条路径中最后一个相同节点就是公共祖先 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* …

纯血鸿蒙APP实战开发——Web获取相机拍照图片案例

介绍 本示例介绍如何在HTML页面中拉起原生相机进行拍照&#xff0c;并获取返回的图片。 效果预览图 使用说明 点击HTML页面中的选择文件按钮&#xff0c;拉起原生相机进行拍照。完成拍照后&#xff0c;将图片在HTML的img标签中显示。 实现思路 添加Web组件&#xff0c;设置…

(实测验证)【移远EC800M-CN 】GNSS功能打开和关闭关闭步骤验证

引言 本文章使用自研“超小体积TTL转4GGPS集成模块”进行实测验证&#xff1b; 一、打开GNSS功能 步骤一、通过 ATQGPSCFG 配置 GNSS 参数 &#xff08;1&#xff09;该命令用于查询和配置 GNSS 不同的设置&#xff0c;包括 NMEA 语句输出端口、NMEA 语句的输出类型等。 1.1…

Trinity部署、使用与原理分析

文章目录 前言1、概述1.1、整体架构1.2、trinity-main1.3、childx 2、安装与使用2.1、源码安装2.1.1 部署系统依赖组件2.1.2 使用源码安装系统 2.2、使用方法 3、测试用例3.1、Splice系统调用压力测试3.2、其它系统调用压力测试3.3、自定义系统调用压力测试 4、总结4.1、部署架…