> ### 线程池的优点
1. 提升性能:它们通常在执行大量异步任务时,由于减少了每个任务的调用开销,并且它们提供了一种限制和管理资源(包括线程)的方法,使得性能提升明显;
2. 统计信息:每个ThreadPoolExecutor保持一些基本的统计信息,例如完成的任务数量。
> ### 线程池实现
- Executors提供的几种线程池:
1. FixedThreadPool:它是一种线程数量固定的线程池,当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭了。当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。由于FixedThreadPool只有核心线程并且这些核心线程不会被回收,这意味着它能够更加快速地响应外界的请求。
```
// 实现方法 规定了核心和最大线程池大小,并使两者一致,使用无界队列(LinkedBlockingQuene)。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
```
2. CachedThreadPool:是一种线程数量不定的线程池,它只有非核心线程,并且其最大线程数为Integer.MAX_VALUE。从CachedThreadPool的特性来看,这类线程池比较适合执行大量的耗时较少的任务,当整个线程池都处于闲置状态时,线程池中的线程都会超时而被停止,这个时候CachedThreadPool之中实际上是没有任何线程的,它几乎是不占用任何系统资源的。
```
// 实现方法 核心线程池为0,最大线程池无界,使用无缓存队列(SynchronousQuene)。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
```
3. ScheduledThreadPool:它的核心线程数是固定的,而非核心线程数是没有限制的,并且当非核心线程闲置时会被立即回收。只要用于执行定时任务和具有固定周期的重复任务。
```
// 实现方法
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
```
4. SingleThreadExecutor:该线程池内部只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。SingleThreadExecutor的意义在于统一所有的外界任务到一个线程中,这使得在这些人物之间不需要处理线程同步问题。
```
// 实现方法 规定核心、最大线程池数量都为1,使用无界队列(LinkedBlockingQuene), 且线程池相关参数不可改变
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));}
```
* 自定义实现线程池:
继承`ThreadPoolExecutor`并提供一个可以传入`corePoolSize`、`maxPoolSize`、`watiTime`、`timeUnit`、`blockingDeque`、`threadFactory`、`rejectPolicy`等相关参数的构造器。
```
/**
* @param corePoolSize:核心线程数量
* @param maxPoolSize:最大线程数量
* @param watiTime:空闲线程等待时间
* @param timeUnit:时间单位
* @param blockingDeque:等待队列
* @param threadFactory:线程工厂
* @param rejectPolicy:拒绝策略
**/
public void createThread(int corePoolSize, int maxPoolSize, long watiTime,
TimeUnit timeUnit, BlockingDeque blockingDeque, ThreadFactory threadFactory,
RejectedExecutionHandler rejectPolicy){
// 生成一个线程池 (同时可以使用其提供的两个钩子来定义线程执行前后的代码)
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, watiTime, timeUnit, blockingDeque, threadFactory, rejectPolicy){
public void beforeExecute(Runnable r, Throwable t){ // 线程执行前
}
public void afterExecute(Runnable r, Throwable t){ // 线程执行后
}
};
// 执行
threadPoolExecutor.execute(new Runnable(){
public void run(){
// 线程执行代码
}
});
// 关闭线程池 等待所有正在执行及等待队列的线程执行完毕后关闭
threadPoolExecutor.shutdown();
}
```
> ### 线程池中线程执行顺序
![](https://img.kancloud.cn/8c/c5/8cc5034dd1acaab9fe1e4c54ab838fea_1238x446.png)
```
任务--->核心线程池--->等待线程池--->最大线程池---->拒绝策略
```
1. 任务到核心线程池看是否有少于核心线程数量(corePoolSize)的线程正在运行,如果有,即使其他工作线程处于空闲状态,也会创建一个新线程来处理该请求。
2. 如果核心线程池全都在工作状态,查看等待队列(blockingDeque)是否已经满了,未满该线程加入到等待队列。
3. 如果等待队列已经满了,查看最大线程池(maxPoolSize)是否已经满了,没有就新建一个线程立刻执行,直到超过最大线程池数量。
4. 如果超出最大线程池了,则执行拒绝策略(RejectedExecutionHandler)。
> ### 等待队列
- 等待队列的类型有四种:
1.ArrayBlockingQueue:有边界的数组阻塞队列,FIFO(先进先出),当超过边界时,则执行相应的拒绝策略。
2.LinkedBlockingQuene:无边界的阻塞队列,当超过corePoolSize时,会一直创建线程,然后再从队列中执行任务,相当于maximumPoolSize无效。
3.SynchronousQuene:无缓存队列,生产者产生一个任务到队列,必须有一个任务从队列中被执行,也就是说新的任务进来时,会创建线程来执行,当线程数超过maximumPoolSize时,执行拒绝策略。
4.PriorityBlockingQueue:具有优先级的无边界队列,根据参数comparator实现。
> ### 拒绝策略
- ThreadPoolExecutor 静态内部类提供4种拒绝策略:
1. AbortPolicy 直接报错
2. CallerRunsPolicy 直接执行Runnable里的run方法,该策略有可能造成主线程的阻塞
3. DiscardPolicy 什么也不做,不报错,也不执行。
4. DiscardOldestPolicy 最先进入队列的线程出队,然后ThreadPoolExecutor再执行该线程。
- 自定义拒绝策略
实现 RejectedExecutionHandler 并重写其 rejectedExecution(Runnable r, ThreadPoolExecutor e) 方法;
- 2111总结
- 1.面向对象
- 1.0.1 super()与this()的区别
- 1.0.2 private、default、protected、public的访问范围
- 1.0.3 continue、break、return区别
- 1.0.4 重载和重写的区别
- 1.0.5 final的特点
- 1.0.6 抽象类与接口的区别
- 1.0.7 java类型
- 1.0.8 什么是反射
- 1.0.9 类的加载机制
- 1.1.1 jvm内存结构
- 1.1.2 java垃圾回收机制
- 1.1.3 并发问题
- 1.1.3.1 线程的状态与关系
- 1.1.3.2 并发的三大性质
- 1.1.3.3 线程的实现与使用
- 1.1.3.4 线程池相关
- 1.1.3.5 并发相关方法
- 1.1.3.6 线程相关工具
- 1.1.4 jdk8特性
- 1.1.4.1 lambad表达式的使用
- 1.1.4.2 stream API
- 1.1.4.3 Optional容器使用
- 1.1.4.4 LocalDateTime
- 1.15 io流
- 1.16 动态代理实现
- 2.JavaEE
- 2.0.1 JSP四大作用域九大内置对象
- 2.0.2 cookie与session的区别
- 4.数据库相关
- 5.git版本管理
- 7.一些问题解决
- 7.1 分布式锁如何实现