ThreadPoolExecutor线程池
Executor的继承结构:
ForkJoinPool:ForkJoinPool运用了Fork/Join原理,将大任务分拆成小任务分配给多个线程执行,最后合并得到最终结果,加快运算。
ThreadPoolExecutor:和ForkJoinPool一样继承 AbstractExecutorService类。
ThreadPoolExecutor线程池的相关参数:
- corePoolSize:线程池核心线程数的多少;
- maximumPoolSize:线程池的最大线程数;
- keepAliveTime:当线程中空闲线程数量超过orePoolSize,多余的线程会在多长时间销毁;
- unit:keepAliveTime的时间单位;
- workQueue:用来存储等待执行的任务的队列;
- threadFactory:线程工厂,用于创建线程,用默认即可;
- handler:(RejectedExecutionHandler)饱和策略;
线程池大小选择策略(参考):
- 大量工作都是计算类的:CPU核数+1;
- 大量进行I/O操作:CPU核数*(1+平均等待时间 / 平均工作时间);
线程池工作流程(下面为测试代码):
package threadPool; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ThreadPoolSimple { public static void main(String[] args) { ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,200, TimeUnit.MILLISECONDS,new ArrayBlockingQueue<Runnable>(5)); for(int i=0;i<15;i++){ MyTask myTask = new MyTask(i); executor.execute(myTask); System.out.println("线程池中线程数目:"+executor.getPoolSize()+" 队列中等待执行的任务数目:"+executor.getQueue().size()+" 已经执行的任务数目:"+executor.getCompletedTaskCount()); } } } class MyTask implements Runnable{ private int taskNum; public MyTask(int num) { this.taskNum = num; } public void run() { System.out.println("正在执行的task>>>"+taskNum); try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("task"+taskNum+"执行完毕!!!"); } }
运行结果:
上图中的标注的结果可以看出:
此时的核心线程数为 5 ,当核心线程数满了过后,新来的任务会添加工作队列中,此时设定的工作队列为 5 ,而循环的任务有15个,就当工作队列也满了,这时候设置的最大线程数(10)还未满,这个时候还会创建新的线程来执行任务,直至最大线程数到达最大值。此时线程池支持的工作任务就是15个(最大线程数+工作队列的大小);
干坏事:将循环的任务改为 >15 个,此时的线程池就支撑不了这么多任务了。所以就会抛出异常;