1.ThreadPoolExeCutor是什么?
线程池的作用是为了解决频繁创建和销毁线程的性能问题,类似的有MySQL连接池。
2.基础介绍
ThreadPoolExecutor得7个参数
ThreadPoolExecutor最常用的构造方法有7个参数如下:
1.corePoolSize(核心线程数),核心线程数可以理解为公司的人员。无论忙还是不忙你都在公司上班,不会说闲的时候就被开除。
2.maximumPoolSize(最大线程数),最大线程数可以理解为公司最多的员工能达到多少,包括了外包人员。
3.keepAliveTime(非核心线程存活时间),非核心线程可以理解为公司的外包人员,存活时间就是指外包在公司最多只能待多久时间,超过这个时间就要离开。
4.unit(非核心线程存活时间单位)
5.workQueue(任务队列),任务队列是指线程提交的任务存放的地方,可以理解为公司的需求量太大,此时本部人员忙不过来了。先把任务放在一个队列中,等核心人员有空了就去处理,如果任务队列也放不下了,此时就叫外包人员来帮忙。
6.threadFactory(线程工厂),用于线程的生产。
7.handler(拒绝策略),前面说过如果任务太多核心线程忙不过来,此时交给任务队列,而任务队列也满了,此时如果最大线程数就是核心线程数,执行拒绝策略。如果新加非核心线程,如果非核心线程+核心线程大于最大线程数执行拒绝策略。
拒绝策略与自定义拒绝策略
拒绝策略是指当核心线程忙不过来的时候,同时任务队列满了,线程数大于最大线程数的时候此时线程池的拒绝方式。其中拒绝策略能够进行自定义,Java中提供的4中拒绝策略如下。
1.AbortPolicy(直接抛出RejectedExecutionException异常)
2.CallerRunsPolicy(将任务交给提交任务者执行)
3.DiscardOldestPolicy(丢弃任务队列中最早的任务,)
4.DiscardPolicy(丢弃当前任务)
通过7个参数中的拒绝策略可以看到RejectedExecutionHandler是个接口,所以要自定义拒绝策略只需要实现RejectedExecutionHandler。
为什么阿里规范需要自定义线程池
如果使用Executors中JDK提供好的线程池如newFixedThreadPool、newSingleThreadExecutor、newCachedThreadPool、这些都是使用ThreadPoolExecutor进行实现的,但是他们的工作队列都是采用的无边界的LinkedBlockingQueue,当提交任务过多,核心线程处理不过来的时候,任务会大量堆积在LinkedBlockingQueue中,而此时会造成OOM的异常。原因也就是LinkedBlockingQueue的最大为Integer.MAX_VALUE。
线程池的状态
线程池一共有5种状态
1.RUNNING状态,线程池运行中。能接受新的任务,也会处理队列中的任务。
2.SHUTDOWN状态,线程池调用shutDown方法的时候变成此状态,同时线程池不接受新的任务,但是会处理掉任务队列