忙完双十一再来完善
https://blog.csdn.net/javaloveiphone/article/details/54729821
https://www.cnblogs.com/feiyun126/p/7686302.html
https://mp.weixin.qq.com/s?__biz=MzI3NjU2ODA5Mg==&mid=2247484187&idx=2&sn=d0058d2d39ba820b840779e4256ce6d8&scene=21#wechat_redirect (这篇公众号写的非常棒)
首先自定义一个ThreadFactory,这么做是为了把自定义的线程和系统线程区分开来,方便出问题的时候排查。
然后自定义worker,worker定义了具体要执行的逻辑:
public class AdsQueryWorker implements Runnable{
private Logger logger = LoggerFactory.getLogger(AdsQueryWorker.class);
/**
* 具体执行哪个方法,查询哪个参数
*/
private String queryMethod;
/**
* 计数器
*/
private CountDownLatch latch;
public AdsQueryWorker(String queryMethod, CountDownLatch latch){
this.queryMethod = queryMethod;
this.latch = latch;
}
@Override
public void run(){
try{
if(queryMethod.equals("test")){
System.out.println("do something");
}
}catch(Exception e){
logger.error("exception_while_query_csp_data:{}", e);
}finally{
latch.countDown();
}
}
}
然后定义ExecutorPool:
@Component("adsQueryExecutor")
public class AdsQueryExecutor{
Logger logger = LoggerFactory.getLogger(AdsQueryExecutor.class);
private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(300, 600, 1000, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(400),
new PoolThreadFactory("adsQueryExecutor"),
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
logger.error("ads_qeuery_execute_pool_full! about_to_reject");
}
}
);
/**
* 执行并行查询
* @param dealerId
* @return
*/
public CspTaskDTO doParallelQuery(Long dealerId, CspTaskDAO cspTaskDAO){
//一共要执行2次查询
CountDownLatch latch = new CountDownLatch(2);
//返回结果
CspTaskDTO result = new CspTaskDTO();
//先全部初始化为0,防止出现查询异常后返回值为null
result.initWithZero();
try {
Runnable totalWorker = new AdsQueryWorker("queryTaskNum", latch);
Runnable totalWorker2 = new AdsQueryWorker("queryTaskNum2", latch);
threadPoolExecutor.execute(totalWorker);
threadPoolExecutor.execute(totalWorker2);
// 使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。
latch.await(1000, TimeUnit.MILLISECONDS);
}catch(Exception e){
logger.error("exception_while_execute_ads_query");
}
return result;
}
这里主要是threadPoolExecutor的定义,300是核心线程数量,600是最大线程数量,400是超过了最大线程数量后还可以往queue里面存这么多以备用。
rejectExecutionHandler是定义了抛弃策略,如果超过600+400个线程数后,还有新的线程要执行,会抛弃,这里执行了打印log操作。
使用的时候,直接在使用的类里面注入:adsQueryExecutor, 然后传入相应参数,调用doParalleyQuery方法就行。
使用idea的开发插件,如果使用:Executors.newFixedThreadPool(4); 就会有提示如下:
这个提示写的非常好,留下来以备后用。