1、为什么用线程池
1)降低资源消耗,线程是稀缺资源,所以反复的创建销毁,是非常消耗资源的
2) 提高响应率 ,大量请求高并发,多线程速度快
3)提高线程的可管理性,线程池进行管理和监控
2、线程池继承实现关系
public class ThreadPoolExecutor extends AbstractExecutorService
public abstract class AbstractExecutorService implements ExecutorService
public interface ExecutorService extends Executor
public interface Executor{
void execute(Runnable command);
}
ExecutorService里面放的是管理线程池的方法
Executors
放的是4个创建线程池的方法
第一个是newSingleThreadPoolExcutor 定义一个线程进行使用串行话
第二个是newFixsThreadPoolExcutor定义n个线程进行使用,空闲线程会一直保留
第三个是newCacheThreadPoolExcutor 不用指定线程数,空闲线程不会创建
第四个是 newSheduelThreadPoolExcutor 创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求
都是使用的execute方法进行调用线程池
问什么不建议使用excutors静态工厂创建线程池
因为
newSingleThreadPoolExcutor和
newFixsThreadPoolExcutor他们使用的LinkedBlockingQueue这个队列,他是都是有长度限制的integer.max,当超过了就会报内存溢出的
newCacheThreadPoolExcutor和
newSheduelThreadPoolExcutor 他们允许创建的线程数最多是
integer.maxValue 2^31 超过了就会报内存溢出的
所以建议使用
new ThreadPoolExecutor (
核心线程数,
最大线程数,
线程数量超过corePoolSize,空闲线程的最大超时时间
时间单位,
工作队列,
工厂类,
拒绝策略
)
线程池底层逻辑
1、判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。
2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。
3、判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。
假如提交到线程池中的任务,IO耗时占比是90%,计算耗时占比10%,忽略提交到线程池中的任务数量,在4C8G的机器上,理想情况下线程池中创建多少个线程是最优的
一般平时只埋头写CURD的候选人,难以计算出来,当然也遇到了不少能算出来结果来的,线程数=(1/0.1) * 4 = 40假如e有一类cpu密集性的任务,没有IO操作,日常的时候只有1个任务,流量高峰会有50个任务,4C8G的机器上,使用的线程池,如何设置corePoolSize, maxPoolSize以及BlockingQueue的大小
很显然,日常只需要一个线程,那么corePoolSize=1,而高峰时候,虽然任务有50个,但是只是4C的机器,对于cpu密集型任务,4个线程是最优的,因此理想情况下maxCorePoolSize=4,最后再看看队列,因为队列满了,max才会被创建,而我们需要让max快速被创建出来,又不会出现任务拒绝,因此,可将队列大小设置成46,那么线程池的行为如下:
原文:https://www.cnblogs.com/potentPrince/p/12574190.html