线程池是一种池化思想的实现,在我们的使用中可以减少不断创建和销毁线程而浪费的时间,达到线程复用,管理线程,控制最大并发的作用.
启动线程池
java在executors中提供了三种方法,实质还是通过ThreadPoolExecutor
ExecutorService pool1=Executors.newSingleThreadExecutor();//一池一线程
ExecutorService pool2=Executors.newFixedThreadPool(n);//指定大小
ExecutorService pool3=Executors.newCachedThreadPool();//Integer.MAX_VALUE
线程池参数
- corePoolSize:线程池核心线程数
- maxiumPoolSize:线程池最大线程数,必须大于等于1。
- keepAliveTime:空闲线程的存活时间。
- unit:keepAliveTime的单位
- workQueue:等待队列,被提交但未被执行的任务
- threadFactory:生成线程池中工作线程的线程工厂,用于创建线程,默认即可。
handler:拒绝策略,表示当队列满了并且工作线程大于等于最大线程数时,如何拒绝请求。
拒绝策略
- 当达到最大线程数且等待队列满时,就要启用拒绝策略。
- AbortPolicy(默认):直接抛出RejectedException。
- CallerRunsPolicy:使用调用线程执行任务。
- iscardOldestPolicy:丢弃等待最久的任务。
DiscardPolicy:直接丢弃任务,不做任何处理。
线程池状态
当创建线程池后,初始时,线程池处于RUNNING状态;
如果调用了shutdown()方法,则线程池处于SHUTDOWN状态,此时线程池不能够接受新的任务,它会等待所有任务执行完毕;
如果调用了shutdownNow()方法,则线程池处于STOP状态,此时线程池不能接受新的任务,并且会去尝试终止正在执行的任务;
当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态。
工作原理
1.线程池创建初始化后池中并没有线程.
2.当调用execute方法添加一个请求任务时,线程池就会做以下判断
2.1 如果当前运行的线程数量少于corePoolSize,那么马上创建线程运行这个任务
2.2 如果当前运行的线程数量大于等于corePoolSize,那么将这个任务放进任务队列
2.3 如果当前任务队列已经满了但是当前运行的线程数量少于maxiumPoolSize,那么就要立即创建非核心线程运行这个任务
2.4 如果当前任务队列满了并且正在运行的线程数量大于等于maxiumPoolSize,那么线程池就会启动饱和拒绝策略
3.当一个线程完成任务后,它会从队列中取下一个任务来执行
4.当一个线程无事可做超过一定时间(keepAliveTime),线程池就会判断:如果当前运行的线程数大于corePoolSize,那么这个线程就会被停掉。所以线程池所有任务完成之后,最终会收缩到corePoolSize的大小。
线程池为什么要构建空任务的非核心线程?
可能存在阻塞队列有任务但没有工作线程的情况。造成这种情况的原因有两点:
1.核心线程数设置为0
2.默认情况下核心线程不会关闭,但可以通过参数设置。如果在任务进入阻塞队列之前,核心线程正好超时关闭也会造成这种问题。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。