[Java线程] CountDownLatch使用

 CountDownLatch可以用来让一个或多个线程等待,如下代码所示:

public class TestCountDownLatch {


    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(2);

        Long start = System.currentTimeMillis();
        System.out.println(String.format("Thread: %s start: %d", Thread.currentThread(), start));
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        executorService.submit(new Handler(countDownLatch));
        executorService.submit(new Handler(countDownLatch));
        try {
            if(!countDownLatch.await(2000, TimeUnit.MILLISECONDS)){
                System.out.println(String.format("Thread: %s time elapses: %d", Thread.currentThread(), System.currentTimeMillis() - start));
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(String.format("Thread: %s duration: %d", Thread.currentThread(), System.currentTimeMillis() - start));
    }

    static class Handler implements Runnable{
        CountDownLatch countDownLatch;

        Handler(CountDownLatch countDownLatch){
            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            long start = System.currentTimeMillis();
            System.out.println(String.format("Thread: %s start: %d", Thread.currentThread(), start));
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(String.format("Thread: %s duration: %d", Thread.currentThread(), System.currentTimeMillis() - start));
            countDownLatch.countDown();
        }
    }
}

 结果输出:

Thread: Thread[main,5,main] start: 1553483802605
Thread: Thread[pool-1-thread-1,5,main] start: 1553483802634
Thread: Thread[pool-1-thread-2,5,main] start: 1553483802634
Thread: Thread[main,5,main] time elapses: 2033
Thread: Thread[main,5,main] duration: 2033
Thread: Thread[pool-1-thread-2,5,main] duration: 5002
Thread: Thread[pool-1-thread-1,5,main] duration: 5002

 实际使用过程中,可以用来控制多个线程等待,CountdownLatch作为结束等待信号。比如说我有一个任务,可以拆分成多个子任务并行执行,最后将执行结果汇总,如下是我在实际生产环境用的代码,一个人有多个联系人电话,我需要拿到每个电话关联的信息,最后汇总在一起,如下代码所示:

CountDownLatch latch = new CountDownLatch(mobile.size()) //mobile是电话数组,每个电话号码都单独处理
        mobile.each {m ->

            CompletableFuture.supplyAsync({
                //add log
                String notifyId = null
                try{
                    ValidateService validateService = getValidateService()
                    String modelid = String.valueOf(attributes.get("modelid"))
                    AddLogVO vo = new AddLogVO()
                    vo.setAppid(_notification.getAppid())
                    vo.setDatatype("online.forecastscore.v3")
                    vo.setSource("mq-service")
                    vo.setTaskId(_notification.getTaskid())
                    vo.setClientAppKey(_notification.getClientappkey())
                    vo.setKeyword(String.valueOf(m.value) + modelid.substring(modelid.length()-1))
                    vo.setQueryParams(String.valueOf(m.value))
                    notifyId = validateService.addLog(vo)
                }catch (Exception ex){
                    logger.warn(String.format("Create log failure ex: %s", ex.getMessage()), ex)
                }

                def _notification = JSON.parseObject(JSON.toJSONString(notification),PullDataNotification.class)
                _notification.notifyId = notifyId
                _notification.datatype = "online.forecastscore.v3"
                _notification.attributes.mobile = m.value
                _notification.attributes.contactType = m.key
                pullNotificationService.dispatchNotification(_notification)  //每个电话号码都去拉取数据
            }).thenApply({
                latch.countDown() //
            })
        }
        //如果等待10秒发现还没有结束
        if(!latch.await(3000, TimeUnit.MILLISECONDS)){ //为了防止无限等待,设置超时时间
            logger.warn(String.format("user3rd.forecastscore.v3 run timeout..."))
            status = 2
        }

注意上面的 latch.await() 方法,为了防止无限等待子线程,设置超时时间。

猜你喜欢

转载自www.cnblogs.com/zhengwangzw/p/10592744.html