什么是线程池
问题: 在程序中频繁的进行连接-中断-连接会浪费大量资源。
解决: 将这些连接资源,放在一个池子当中。通过复用来提升性能
具体: 先启动若干数量的线程,并让这些线程都处于睡眠状态,当需要一个开辟一个线程去做具体的工作时,就会唤醒线程池中的某一个睡眠线程,让它去做具体工作,当工作完成后,线程又处于睡眠状态,而不是将线程销毁。
优点
- 降低资源消耗
- 提高响应
- 方便管理
使用
三大方法
public class PoolTest {
public static void main(String[] args) {
Executors.newCachedThreadPool();//可伸缩的,最大21亿
Executors.newSingleThreadExecutor();//单个线程
Executors.newFixedThreadPool(5);//创建固定大小的线程池
}
}
复制代码
七大参数
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
复制代码
由此我们可以看出这三个方法的本质都是调用ThreadPoolExecutor来执行的。
而我们点进ThreadPoolExecutor的源码一看
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
复制代码
发现调用了一个this,出于好奇我们再看看这个this是什么
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
复制代码
由此我们可以得知其本质是ThreadPoolExecutor的构造函数,其中有七大参数
int corePoolSize, //核心线程数
int maximumPoolSize, //最大线程数
long keepAliveTime, // 每隔多久检查线程是否健康
TimeUnit unit, // 检查的时间单位
BlockingQueue<Runnable> workQueue, //阻塞队列
ThreadFactory threadFactory, // 线程工厂
RejectedExecutionHandler handler //拒绝策略
复制代码
- corePoolSize是我们平时线程池最多开启线程的数量
- 当超过该数量时就存入阻塞队列workQueue进行等待
- 如果阻塞队列workQueue放不下了,我们就多开启线程使其达到maximumPoolSize个。
- 如果还不够则根据拒绝策略handler对超过的线程进行拒绝,
四种拒绝策略
- ThreadPoolExecutor.AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常。
- ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
- ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务(和最早的竞争,不抛异常)
- ThreadPoolExecutor.CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务,哪来的回哪去
如何定义最大线程数maximumPoolSize
- CPU密集型:有几个cpu就设置几个,cpu利用率最大
- IO密集型: 判断有大量IO的线程有几个,只要大于这个数量即可。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END