package com.clothes.manage.util;
import java.util.concurrent.*;
public class ThreadPoolUtil {
/**
* 线程池的基本大小
*/
int corePoolSize = 4;
/**
* 线程池最大数量
*/
int maximumPoolSizeSize = 6;
/**
* 线程活动保持时间
*/
long keepAliveTime = 2;
/**
* 任务队列
*/
//LinkedBlockingQueue workQueue = new LinkedBlockingQueue();
BlockingQueue<Runnable> workQueue=new ArrayBlockingQueue<Runnable>(2);
public ThreadPoolExecutor CreateThreadPool() {
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSizeSize,
keepAliveTime,
TimeUnit.SECONDS,
workQueue,
new ThreadPoolExecutor.AbortPolicy()
);
return executor;
}
//private static ThreadPool instance=new ThreadPool();
// public static ThreadPool getInstance(){
// return instance;
// }
private ThreadPoolUtil() {
}
private static class ThreadPoolInner {
private final static ThreadPoolUtil instance = new ThreadPoolUtil();
}
public static ThreadPoolUtil getInstance() {
return ThreadPoolInner.instance;
}
}
四种拒绝策略的简介
1,AbortPolicy,丢弃任务并抛出RejectedExecutionException异常,这是线程池默认的拒绝策略,在任务不能再提交的时候,抛出异常,及时反馈程序运行状态。如果是比较关键的业务,推荐使用此拒绝策略,这样子在系统不能承载更大的并发量的时候,能够及时的通过异常发现。
2,DiscardPolicy,丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。无关紧要的业务可以采用此策略
3,DiscardOldestPolicy,弃队列最前面的任务,然后重新提交被拒绝的任务。喜新厌旧型的拒绝策略。
4,CallerRunsPolicy ,如果任务被拒绝了,则由调用线程(提交任务的线程)直接执行此任务。
也可以自定义拒绝策略,重写RejectedExecutionHandler 的rejectedExecution的方法
package com.clothes.manage.util;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class RejectedTest implements RejectedExecutionHandler {
public RejectedTest(){}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from zhs " +
executor.toString());
}
}
测试
ThreadPoolExecutor threadPoolExecutor=null;
try {
threadPoolExecutor=ThreadPoolUtil.getInstance().CreateThreadPool();
for (int i = 0; i <20 ; i++) {
final int index=(i+1);
threadPoolExecutor.submit(()->{
System.out.println("线程"+index);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread.sleep(500);
}
if(threadPoolExecutor.isTerminated()){
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
threadPoolExecutor.shutdown();
// while (true) {
// if (threadPoolExecutor.isTerminated()) {
// System.out.println("多线程执行完成************************************");
// break;
// }
//
// System.out.println("线程池执行中。");
// }
}
当我把线程池配置调整
50个任务去执行的时候,拒绝策略选用CallerRunsPolicy 的时候,来分析下线程池的执行逻辑
pool-1-thread-1***1
阻塞队列大小0
pool-1-thread-2***2
阻塞队列大小0
pool-1-thread-3***3
阻塞队列大小0
pool-1-thread-4***4 // 核心线程数用完了,开始阻塞
阻塞队列大小0
阻塞队列大小1
阻塞队列大小2
阻塞队列大小3
阻塞队列大小4
阻塞队列大小5
阻塞队列大小6
阻塞队列大小7
阻塞队列大小8
阻塞队列大小9
阻塞队列大小10 // 阻塞队列满了,开始开启更多的线程去执行
pool-1-thread-5***15
阻塞队列大小10
pool-1-thread-6***16
阻塞队列大小10
pool-1-thread-7***17
阻塞队列大小10
pool-1-thread-8***18
阻塞队列大小10
pool-1-thread-9***19
阻塞队列大小10
pool-1-thread-10***20
pool-1-thread-1***5 //线程数达到10了, 但前面的线程执行完了,开始执行队列中的的任务
阻塞队列大小9
pool-1-thread-2***6
阻塞队列大小9
pool-1-thread-3***7
阻塞队列大小9
pool-1-thread-4***8
阻塞队列大小9
阻塞队列大小10 // 队列又满了
main***25 // 根据拒绝策略的设置,main线程开始帮忙执行任务了
pool-1-thread-5***9 // 前面的线程开始再次执行任务了
pool-1-thread-6***10
pool-1-thread-7***11
pool-1-thread-8***12
pool-1-thread-9***13
pool-1-thread-10***14
pool-1-thread-1***21
pool-1-thread-2***22
pool-1-thread-3***23
pool-1-thread-4***24
阻塞队列大小0
阻塞队列大小1
阻塞队列大小2
阻塞队列大小3
阻塞队列大小4
阻塞队列大小5
阻塞队列大小6
阻塞队列大小7
阻塞队列大小8
pool-1-thread-5***26
阻塞队列大小8
pool-1-thread-6***27
阻塞队列大小8
pool-1-thread-7***28
阻塞队列大小8
pool-1-thread-8***29
阻塞队列大小8
pool-1-thread-9***30
阻塞队列大小8
pool-1-thread-10***31
阻塞队列大小8
pool-1-thread-1***32
阻塞队列大小8
pool-1-thread-2***33
阻塞队列大小8
pool-1-thread-3***34
阻塞队列大小8
pool-1-thread-4***35
阻塞队列大小8
阻塞队列大小9
阻塞队列大小10
main***46 // 又来帮忙了
pool-1-thread-5***36
pool-1-thread-6***37
pool-1-thread-7***38
pool-1-thread-8***39
pool-1-thread-9***40
pool-1-thread-10***41
pool-1-thread-1***42
pool-1-thread-2***43
pool-1-thread-3***44
pool-1-thread-4***45
阻塞队列大小0
阻塞队列大小1
阻塞队列大小2
阻塞队列大小3
阻塞队列大小4
pool-1-thread-5***47
pool-1-thread-6***48
pool-1-thread-7***49
pool-1-thread-8***50 // 50个任务执行完毕了,如果选用其他拒绝策略的时候,必然丢弃了一些任务,就达不到50个了