列举一个线程池max=6,core=3,任务队列taskQueue=5;采用饱和策略为1)
则我们看看提交任务给此线程池的执行逻辑如下:
1)首先我们提交第一个任务到线程池,此时核心线程数都还没有用,所以会启动核心线程之一来执行任务
2)接着提交第二个第三个任务到线程池,他们的执行逻辑同第一个任务是一模一样的,线程池会启动核心线程池中剩下的两个线程来执行你新提交的任务。
3)接着又有新的任务提交过来,这个时候线程池发现核心线程池中的线程已经都在工作中,所以会去看任务队列taskQueue是否满了,发现并没有,是空的,所以将这个任务放入任务队列中等待核心线程池中有空闲线程时自己来取任务执行。
4)接着又提交了4个任务到线程池,他们分别判断核心线程是否空闲,不空闲,然后判断任务队列是否已满,不满,则直接将任务放入队列;
5)接着新的任务又来,则在判断核心线程池和任务队列之后,发现任务依然没有办法处理,(max=6,core=3正在执行任务,新来一个线程,3+1<6,此时队列taskQueue已经满了,corepoolsize=3也都在干活)则会判断是否线程数达到最大,发现没有,则新启动线程来执行任务;(新的任务开始加入到执行任务中,3个corepoolsize+1个非核心线程,此时执行任务4,可理解新添加的任务是非核心线程任务在执行任务)
6)接着又来一个任务,执行流程同5,(此时有5个线程在执行任务,2个非核心线程在执行任务,3个corepoolsize在执行任务);
7)接着又来一个任务,执行流程同5,(此时有6个线程在执行任务,3个非核心线程在执行任务,3个corepoolsize在执行任务);
8)再来一个任务,发现核心线程池在忙,任务队列也满了,线程池中的全部线程也都在工作(3个corepoolsize+3个非核心线程=max(6)都在工作,如果加入新的线程则3个corepoolsize+4个非核心线程>max(6),将报拒绝异常),没有办法处理他了,所以他找到了饱和策略,因为饱和策略是默认的抛异常,所以线程池会告诉提交任务的线程,已经没有可以用的线程了。
以上就一个核心线程数是3,总线程数是6,任务队列长度为5,默认策略采用抛异常的策略的从最开始到最后线程池满负荷运作的过程
关注点1 线程池大小
线程池有两个线程数的设置,一个为核心池线程数,一个为最大线程数。
在创建了线程池后,默认情况下,线程池中并没有任何线程,等到有任务来才创建线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法
当创建的线程数等于 corePoolSize 时,会加入设置的阻塞队列。当队列满时,会创建线程执行任务直到线程池中的数量等于maximumPoolSize。
关注点2 适当的阻塞队列
java.lang.IllegalStateException: Queue full
方法 抛出异常 返回特殊值 一直阻塞 超时退出
插入方法 add(e) offer(e) put(e) offer(e,time,unit)
移除方法 remove() poll() take() poll(time,unit)
检查方法 element() peek() 不可用 不可用
ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
DelayQueue: 一个使用优先级队列实现的无界阻塞队列。
SynchronousQueue: 一个不存储元素的阻塞队列。
LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。
LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。
关注点3 明确拒绝策略
ThreadPoolExecutor.AbortPolicy: 丢弃任务并抛出RejectedExecutionException异常。 (默认)
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
说明:Executors 各个方法的弊端:
1)newFixedThreadPool 和 newSingleThreadExecutor:
主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至 OOM。
2)newCachedThreadPool 和 newScheduledThreadPool:
主要问题是线程数最大数是 Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至 OOM。
https://blog.csdn.net/qq_33581278/article/details/84568675