线程池的优势:
线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后再线程创建后启动这些任务,如果线程数量超过最大数量,超过数量的线程排队等待,等其他线程执行完毕,再从队列中取出任务来执行。
它的主要特点是:线程复用;控制最大并发数;管理线程。
第一:降低资源消耗。通过重复利用已经创建的线程降低线程创建和销毁造成的消耗。
第二:提高响应速度。当任务到达时,任务可以不需要等待线程创建就能立即执行。
第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
线程池如何使用
底层原理
七大参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1、corePoolSize:核心线程数,线程池中常驻核心线程数
2、maximumPoolSize:线程池中能够容纳同时执行线程的最大数量,此值必须大于等于1
3、keepAliveTime:多余的空闲线程的存活时间当前池中线程数量超过corePoolSize时,当空闲时间达到keepAliveTime时,多余线程会被销毁直到只剩下corePoolSize个线程位置。
4、unit:keepAliveTime的单位
5、workQueue:任务队列,被提交但尚未被执行的任务
6、ThreadFactory:标识生成线程池中工作线程的线程工厂,用于创建线程,一般默认的即可。
7、handler:拒绝策略,表示当前队列满了,并且工作线程大于等于线程池的最大线程数时如何来拒绝请求执行的runnable的策略。
工作原理
1、在创建线程池后,线程中的线程数为0
2、当调用execute()方法添加
线程池用哪个生产中如何设置合理参数?
在工作中单一的/固定的/可变的三种创建线程池的方法哪个用的多?超级大坑
工作中需要自己手写线程池!
拒绝策略
等待队列已经排满了,再也塞不下新任务了,同时,线程池中的max线程也达到了,无法继续为新任务服务,这个时候我们需要拒绝策略机制合理的处理这个问题。
- AbortPolicy(默认):直接抛出RejectedExceutionException异常阻止系统正常运行。
- CallerRunsPolicy:"调用者运行"一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。
- DiscardOldestPolicy():抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。
- DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种策略。
手写线程池
public class MyThreadPoolDemo {
public static void main(String[] args) {
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3L,
TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy()
// new ThreadPoolExecutor.DiscardOldestPolicy()
// new ThreadPoolExecutor.CallerRunsPolicy()
// new ThreadPoolExecutor.AbortPolicy()
);
for(int i=1;i<=20;i++){
int finalI = i;
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"号业务员办理业务"+ finalI);
});
}
}
}