newCachedThreadPool:可复用线程池,线程数量无限制,容易cpu100%,队列并非无界队列,相较而言最不容易出现OOM
newFixedThreadPool:固定大小线程池,无边界阻塞队列,容易内存溢出(OOM)
newSingleThreadPool:只有一个线程
线程池核心参数:
corePoolSize:核心线程数。默认情况下,核心线程会一直存活,但是当将allowCoreThreadTimeout设置为true时,核心线程也会超时回收。
maximumPoolSize:线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。
keepAliveTime:线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将allowCoreThreadTimeout设置为true时,核心线程也会超时回
unit:指定keepAliveTime参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)。
workQueue:任务队列。通过线程池的execute()方法提交的Runnable对象将存储在该参数中。其采用阻塞队列实现。
threadFactory:线程工厂。用于指定为线程池创建新线程的方式。
handler:拒绝策略。当达到最大线程数时需要执行的饱和策略。
线程池工作原理
1. 当调用 execute() 方法添加一个任务时,线程池会做如下判断:
a) 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务;
b) 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列;
c) 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要
创建非核心线程立刻运行这个任务;
d) 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池
会抛出异常 RejectExecutionException。
2. 当一个线程完成任务时,它会从队列中取下一个任务来执行。
3. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。
4.当设置allowCroeThreadTimeOut=true时,任何空闲时间超过keepaliveTime的线程都会被销毁
(macxia查看继承关系图快捷键:command+option+shift+u)
execute和submit的区别
1、submit中调用了execute方法,submit有返回值,execute无返回值
2、可以接受的任务类型不同,execute只能接受Runnable类型的任务,submit不仅可以接受Runnable还可以接受Callable的任务
3、submit可以进行exception处理
run和start的区别
run方法:普通方法,直接在当前线程中去执行run()方法
start方法:创建一个新线程去执行run方法
提交优先级:就是先交付核心线程、等待队列、非核心线程
线程池内部调用过程
执行优先级 :核心线程、非核心线程、等待队列
在内部调用过程中,队列的优先级是最低的(这个逻辑从源码中可以看出):
拒绝策略: