ThreadPoolExecutor

忙完双十一再来完善

 

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,这么做是为了把自定义的线程和系统线程区分开来,方便出问题的时候排查。

ThreadPoolExecutor_第1张图片

然后自定义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); 就会有提示如下:

ThreadPoolExecutor_第2张图片

这个提示写的非常好,留下来以备后用。

 

转载于:https://my.oschina.net/u/3755458/blog/2252630

你可能感兴趣的:(开发工具)