一.Java线程池七大参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) { ... }
1.corePoolSize(核心线程数):创建线程池后不会立即创建核心线程,当有任务到达时才触发核心线程的创建;核心线程会一直存活,即使没有任务需要执行;当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理。(设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时摧毁)
2.maximumPoolSize(最大线程数):当线程数>=corePoolSize且任务队列已满时线程池会创建新线程来处理任务;当线程数=maximumPoolSize,且任务队列已满时,线程池会根据配置的拒绝策略处理任务。
3.keepAliveTime(线程空闲时间):当线程空闲时间达到keepAliveTime时,线程会摧毁,直到线程数量=corePoolSize。(如果allowCoreThreadTimeout=true,则会直到线程数量=0)
4.unit(keepAliveTime的计量单位)
5.workQueue (工作队列):新任务被提交且核心线程数满后,会进入到此工作队列中,任务调度从队列中取出任务。
- SynchronousQueue(直接提交队列):没有容量的容器,每一个插入的操作都要等待相应的删除操作,不保存任务,它总是马上将任务提交给线程执行,如果没有空闲的线程则会尝试创建新的线程,如果线程数量已经达到最大值,则执行拒绝策略,使用次队列通常需要设置很大的maximumPoolSize;
- ArrayBlockingQueue:基于数组的有界阻塞队列,按FIFO排序;
- LinkedBlockingQuene:基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序,若任务创建和处理速度差异很大,无界队列会快速膨胀导致系统资源耗尽 ;
- PriorityBlockingQueue:是一个特殊的无界队列,创建此队列时可以传入Comparator对任务进行优先级处理。
6.threadFactory(创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等)
7.handler (拒绝策略):所有拒绝策略实现RejectedExecutionHandler接口,读者可根据实际情况扩展该接口实现自己的拒绝策略 。
- AbortPolicy策略: 该策略会直接抛出异常 ;
- CallerRunsPolicy策略: 只要线程池未关闭,该策略直接在调用者线程中运行当前被放弃任务 ;
- DiscardOledestPolicy策略: 丢弃最老的一个请求,也就是丢弃一个即将被执行的任务,并尝试再提交当前任务 ;
- DiscardPolicy策略: 该策略丢弃无法处理的任务,不做任何处理 。
二.JDK四个自带线程池
1.newFixedThreadPool (固定大小线程池,核心线程池与最大线程池一致,队列大小为Integer.MAX_VALUE):每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小;线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
public static void main(String[] args) {
// 创建一个固定大小为5的线程池 队列大小为Integer.MAX_VALUE
ExecutorService pool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
pool.submit(()->{
System.out.println(Thread.currentThread().getName() + "处理当前任务");
});
}
pool.shutdown();
}
2.newCachedThreadPool(可缓存线程池):核心线程数为0 ,最大线程数Integer.MAX_VALUE ,队列为SynchronousQueue(直接提交队列);如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲( 60 秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务;此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说 JVM )能够创建的最大线程大小。
public static void main(String[] args) {
//核心线程数为0 最大线程数Integer.MAX_VALUE 队列为SynchronousQueue(直接提交队列)
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 50; i++) {
pool.submit(() -> {
System.out.println(Thread.currentThread().getName() + "处理当前任务");
});
}
pool.shutdown();
}
3.newScheduledThreadPool (创建一个定长线程池,支持定时及周期性任务执行):核心线程数为传入值,最大线程数为Integer.MAX_VALUE,采用优先级队列DelayedWorkQueue;适用场景:调用第三方返回中间状态,可用此状态先轮训查询状态。
public static void main(String[] args) {
//定长线程池,支持定时及周期性任务执行 核心线程数为5,最大线程数为Integer.MAX_VALUE,优先级队列DelayedWorkQueue
ScheduledExecutorService pool = Executors.newScheduledThreadPool(5);
//延时1000毫秒执行
pool.schedule(() -> {
System.out.println(Thread.currentThread().getName() + "延时1000毫秒秒处理当前任务");
}, 1000, TimeUnit.MILLISECONDS);
//延时1000毫秒周期性执行,周期为100毫秒
pool.scheduleAtFixedRate(() -> {
System.out.println(Thread.currentThread().getName() + "周期性执行,周期为100毫秒,处理当前任务");
}, 1000, 100, TimeUnit.MILLISECONDS);
}
4.newSingleThreadExecutor (单线程化的线程池):核心线程数与最大线程数都为1,队列大小为Integer.MAX_VALUE;只有一个线程在工作,也就是相当于单线程串行执行所有任务;如这个唯一的线程因为异常结束,那么会有一个新的线程来替代它;此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
public static void main(String[] args) {
//创建一个单线程的线程池 核心线程数与最大线程数都为1,队列大小为Integer.MAX_VALUE
ExecutorService pool = Executors.newSingleThreadExecutor();
for (int i = 0; i < 20; i++) {
pool.submit(() -> {
System.out.println(Thread.currentThread().getName() + "处理当前任务");
});
}
pool.shutdown();
}