对于线程池ThreadPool的学习总结
线程池:就是一个管理线程的池子。
优点:
- 它帮我们管理线程,避免增加创建线程和销毁线程的资源损耗。因为线程其实也是一个对象,创建一个对象,需要经过类加载过程,销毁一个对象,需要走GC垃圾回收流程,都是需要资源开销的。
- 提高响应速度。 如果任务到达了,相对于从线程池拿线程,重新去创建一条线程执行,速度肯定慢很多。
- 重复利用。 线程用完,再放回池子,可以达到重复利用的效果,节省资源。
一、线程池的创建
线程池可以通过ThreadPoolExecutor来创建
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long
keepAliveTime,TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
//corePoolSize: 线程池核心线程数最大值
//maximumPoolSize: 线程池最大线程数大小
//keepAliveTime: 线程池中非核心线程空闲的存活时间大小
//unit: 线程空闲存活时间单位
//workQueue: 存放任务的阻塞队列
//threadFactory: 用于设置创建线程的工厂,可以给创建的线程设置有意义的名字,可方便排查问题。
//handler: 线城池的饱和策略事件,主要有四种类型。
二、线程池处理流程
1,首先线程池判断基本线程池是否已满(< corePoolSize ?)?没满,创建一个工作线程来执行任务。满了,则进入下个流程。
2,其次线程池判断阻塞队列是否已满?没满,则将新提交的任务存储在阻塞队列里。满了,则进入下个流程。
3,最后线程池判断整个线程池是否已满(< maximumPoolSize ?)?没满,则创建一个新的工作线程来执行任务,满了,则交给饱和策略来处理这个任务。
三、线程池的阻塞队列
线程池阻塞队列:1、有界阻塞队列 2、无界阻塞队列 3、同步移交阻塞队列
public class QueueTest { @Test
public void arrayBlockingQueue() throws InterruptedException {
/**
* 基于数组的有界阻塞队列,队列容量为10
*/
ArrayBlockingQueue queue =
new ArrayBlockingQueue<Integer>(10); // 循环向队列添加元素
for (int i = 0; i < 20; i++) {
queue.put(i);
System.out.println("向队列中添加值:" + i);
}
} @Test
public void linkedBlockingQueue() throws InterruptedException {
/**
* 基于链表的有界/无界阻塞队列,队列容量为10
*/
LinkedBlockingQueue queue =
new LinkedBlockingQueue<Integer>(); // 循环向队列添加元素
for (int i = 0; i < 20; i++) {
queue.put(i);
System.out.println("向队列中添加值:" + i);
}
} @Test
public void test() throws InterruptedException {
/**
* 同步移交阻塞队列
*/
SynchronousQueue queue = new SynchronousQueue<Integer>(); // 插入值
new Thread(() -> {
try {
queue.put(1);
System.out.println("插入成功");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start(); // 删除值
new Thread(() -> {
try {
queue.take();
System.out.println("删除成功");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start(); Thread.sleep(1000L * 60);
} }
四、线程池饱和策略
- Caller-runs调用者运行策略,即该线程的执行有调用的这个线程来执行,调用的线程会暂停原来的任务,转而去执行该任务,该任务执行完成后继续执行原来的任务
- AbortPolicy终止策略(系统默认), 该策略保证在线程池满的情况下任何试图提交任务到该线程池的线程的线程均会抛出,RejectedExecutionException,该异常导致调用线程的终止。但这种异常时可以捕获的(非检查型异常)。
- DiscardPolicy抛弃策略,该策略保证任何试图向满的线程池提交任务时,该任务的提交会立即返回,任务不会被提交,并且不会抛出任何形式的异常。
- DiscardOldestPolicy抛弃旧任务策略,这种模式下,将会抛弃下一个将要执行的任务,然后把刚提交的任务添加到任务队列,等待执行。
五、线程池的常用线程池
- newCachedThreadPool (创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。)
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(
0, // corePoolSoze == 0
Integer.MAX_VALUE, // maximumPoolSize 非常大
60L, // 空闲判定是60 秒
TimeUnit.SECONDS,
// 神奇的无存储空间阻塞队列,每个 put 必须要等待一个 take
new SynchronousQueue<Runnable>()
);
} newFixedThreadPool (创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。)
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(
nThreads, // corePoolSize
nThreads, // maximumPoolSize == corePoolSize
0L, // 空闲时间限制是 0
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>() // 无界阻塞队列
);
}newSingleThreadPool (创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。)
public static ExecutorService newSingleThreadExecutor() {
return
new FinalizableDelegatedExecutorService
(
new ThreadPoolExecutor
(
1,
1,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory
)
);
}newScheduleThreadPool (创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。)
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
六、向线程池提交任务
提交任务有两种方式:1、有返回结果-sunmit 2、无返回结果-execute
public class RunTest { @Test
public void submitTest()
throws ExecutionException, InterruptedException { // 创建线程池
ExecutorService threadPool =
Executors.newCachedThreadPool(); /**
* 利用submit方法提交任务,接收任务的返回结果
*/
Future<Integer> future = threadPool.submit(() -> {
Thread.sleep(1000L * 10); return 2 * 5;
}); /**
* 阻塞方法,直到任务有返回值后,才向下执行
*/
Integer num = future.get(); System.out.println("执行结果:" + num);
} @Test
public void executeTest() throws InterruptedException {
// 创建线程池
ExecutorService threadPool =
Executors.newCachedThreadPool(); /**
* 利用execute方法提交任务,没有返回结果
*/
threadPool.execute(() -> {
try {
Thread.sleep(1000L * 10);
} catch (InterruptedException e) {
e.printStackTrace();
} Integer num = 2 * 5;
System.out.println("执行结果:" + num);
}); Thread.sleep(1000L * 1000);
} }
关于线程池五种状态:
线程池的5种状态:RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED.
1、RUNNING
(1). 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。
(2). 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0!
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
2、 SHUTDOWN
(1). 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
(2). 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
3、STOP
(1). 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
(2). 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
4、TIDYING
(1). 状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。
当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;
可以通过重载terminated()函数来实现。
(2). 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。
当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。
5、 TERMINATED
(1). 状态说明:线程池彻底终止,就变成TERMINATED状态。
(2). 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
最后实践Springboot中线程池的使用
@Configuration
@EnableAsync
public class ExecutorConfig { @Bean("exportServiceExecutor")
public Executor exportServiceExecutor(){
//创建线程池
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数量:当前机器核心数
executor.setCorePoolSize (
Runtime.getRuntime().availableProcessors());
//最大线程数
executor.setMaxPoolSize(
Runtime.getRuntime().availableProcessors() * 2);
//队列大小
executor.setQueueCapacity(Integer.MAX_VALUE);
//线程池中线程名前缀
executor.setThreadNamePrefix("export-");
//线程池阻塞策略-拒绝策略:直接拒绝
executor.setRejectedExecutionHandler(
new ThreadPoolExecutor.AbortPolicy());
return executor;
}
}
@Async("exportServiceExecutor") //指定线程池
public void executorTest(){
System.out.println("测试线程");
}
对于线程池ThreadPool的学习总结的更多相关文章
- 关于线程池ThreadPool的学习
学习重点ThreadPool.SetMinThreads(out workerThreads, out completionPortThreads).这是整个线程池的关键. 而ThreadPool. ...
- java核心知识点学习----重点学习线程池ThreadPool
线程池是多线程学习中需要重点掌握的. 系统启动一个新线程的成本是比较高的,因为它涉及与操作系统交互.在这种情形下,使用线程池可以很好的提高性能,尤其是当程序中需要创建大量生存期很短暂的线程时,更应该考 ...
- C#多线程学习 之 线程池[ThreadPool](转)
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- C#多线程学习 之 线程池[ThreadPool]
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- [转]C#多线程学习 之 线程池[ThreadPool]
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- 多线程系列 线程池ThreadPool
上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...
- 多线程系列(2)线程池ThreadPool
上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...
- 线程池ThreadPool实战
线程池ThreadPool 线程池概念 常用线程池和方法 1.测试线程类 2.newFixedThreadPool固定线程池 3.newSingleThreadExecutor单线程池 4.newCa ...
- 线程池ThreadPool的初探
一.线程池的适用范围 在日常使用多线程开发的时候,一般都构造一个Thread示例,然后调用Start使之执行.如果一个线程它大部分时间花费在等待某个事件响应的发生然后才予以响应:或者如果在一定期间内重 ...
随机推荐
- 接口中字段的修饰符:public static final(默认不写) 接口中方法的修饰符:public abstract(默认不写)abstract只能修饰类和方法 不能修饰字段
abstract只能修饰类和方法 不能修饰字段
- 如何按名称或PID查找一个进程?如何按端口号查找一个进程?如何查看一个进程的CPU和内存、文件句柄使用情况?如何查看CPU利用率高的TOP10进程清单?如何根据PID强制终止进程?
如何按名称或PID查找一个进程?如何按端口号查找一个进程?如何查看一个进程的CPU和内存.文件句柄使用情况?如何查看CPU利用率高的TOP10进程清单? 目录 如何按名称或PID查找一个进程?如何按端 ...
- Stimulsoft报表工具中属性表达式设置属性表达式
Stimulsoft仪表工具实现所需的数据可视化和自己的信息图表.该产品能够应用必要的过滤器和排序,汇总数据,执行任何复杂度的计算.该产品的优势在于其多功能性-能够为您的业务,财务,销售,行业等任何领 ...
- LC滤波电路分析,LC滤波电路原理及其时间常数的计算
LC滤波器具有结构简单.设备投资少.运行可靠性较高.运行费用较低等优点,应用很广泛. LC滤波器又分为单调谐滤波器.高通滤波器.双调谐滤波器及三调谐滤波器等几种. LC滤波主要是电感的电阻小,直流损耗 ...
- 并发编程——多线程计数的更优解:LongAdder原理分析
前言 最近在学习ConcurrentHashMap的源码,发现它采用了一种比较独特的方式对map中的元素数量进行统计,自然是要好好研究一下其原理思想,同时也能更好地理解ConcurrentHashMa ...
- 痞子衡嵌入式:基于恩智浦i.MXRT1010的MP3音乐播放器(RT-Mp3Player)设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是基于i.MXRT1011的MP3播放器参考设计. i.MXRT1011是恩智浦i.MXRT四位数系列的入门型号,虽然是入门级,可也是50 ...
- ERROR: No matching distribution found for cv2
ImportError: No module named cv2和No matching distribution found for cv2的问题 原因 这个是由于没有导入opencv库导致的 解决 ...
- IOCP三层结构
iocp三层架构服务器模型 分类: GameEngine专题之IOCP(完成端口)2010-04-06 14:44 2611人阅读 评论(0) 收藏 举报 服务器socket工作测试应用服务器性能优化 ...
- day82:luffy:课程详情页面显示&章节和课时显示&视频播放组件&CKEditor富文本编辑器
目录 1.初始课程详情页面 2.视频播放组件 3.课程详情页面后端接口实现 4.课程详情页面-前端 5.CKEditor富文本编辑器 6.课程章节和课时显示-后端接口 7.课程章节和课时显示-前端 1 ...
- canvas生成圆图和微信小程序canvas圆图
先在HTML中创建 img和canvas并设置id属性 <canvas id="canvas" width="500" height="500& ...