7.6 CountdownLatch

CountdownLatch 介绍

用来进行线程同步协作,等待所有线程完成倒计时。
其中构造参数用来初始化等待计数值,await() 用来等待计数归零,countDown() 用来让计数减一。

@Slf4j(topic = "c.TestCountDownLatch")
public class TestCountDownLatch {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);

        new Thread(() -> {
            log.debug("begin...");
            sleep(1000);
            latch.countDown();
            log.debug("end...{}", latch.getCount());
        }).start();

        new Thread(() -> {
            log.debug("begin...");
            sleep(2000);
            latch.countDown();
            log.debug("end...{}", latch.getCount());
        }).start();

        new Thread(() -> {
            log.debug("begin...");
            sleep(1500);
            latch.countDown();
            log.debug("end...{}", latch.getCount());
        }).start();

        log.debug("waiting...");
        latch.await();
        log.debug("wait end...");
    }

    public static void sleep(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

输出

16:55:42.713 [Thread-2] - begin...
16:55:42.713 [Thread-1] - begin...
16:55:42.713 [main] - waiting...
16:55:42.713 [Thread-0] - begin...
16:55:43.716 [Thread-0] - end...2
16:55:44.218 [Thread-2] - end...1
16:55:44.715 [Thread-1] - end...0
16:55:44.715 [main] - wait end...

可以配合线程池使用,改进如下

@Slf4j(topic = "c.TestCountDownLatch")
public class TestCountDownLatch {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        executorService.submit(() -> {
            log.debug("begin...");
            sleep(1000);
            latch.countDown();
            log.debug("end...{}", latch.getCount());
        });
        executorService.submit(() -> {
            log.debug("begin...");
            sleep(2000);
            latch.countDown();
            log.debug("end...{}", latch.getCount());
        });
        executorService.submit(() -> {
            log.debug("begin...");
            sleep(1500);
            latch.countDown();
            log.debug("end...{}", latch.getCount());
        });
        executorService.submit(() -> {
            try {
                log.debug("waiting...");
                latch.await();
                log.debug("wait end...");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }

    public static void sleep(long time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

输出

17:24:36.535 [pool-1-thread-1] - begin...
17:24:36.536 [pool-1-thread-4] - waiting...
17:24:36.535 [pool-1-thread-2] - begin...
17:24:36.535 [pool-1-thread-3] - begin...
17:24:37.542 [pool-1-thread-1] - end...2
17:24:38.042 [pool-1-thread-3] - end...1
17:24:38.541 [pool-1-thread-2] - end...0
17:24:38.541 [pool-1-thread-4] - wait end...

应用

应用之同步等待多线程准备完毕

@Slf4j(topic = "c.TestCountDownLatch")
public class TestCountDownLatch {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        CountDownLatch latch = new CountDownLatch(10);
        Random r = new Random();
        String[] all = new String[10];

        for (int i = 0; i < 10; i++) {
            int k = i;
            executorService.submit(() -> {
                for (int j = 0; j <= 100; j++) {
                    try {
                        Thread.sleep(r.nextInt(100));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    all[k] = j + "%";
                    System.out.print("\r" + Arrays.toString(all));
                }
                latch.countDown();
            });
        }
        latch.await();
        System.out.println("\n游戏开始");
        executorService.shutdown();
    }

}

中间输出

[39%, 32%, 34%, 38%, 39%, 34%, 33%, 32%, 34%, 39%]

最后输出

[100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%, 100%]
游戏开始

应用之同步等待多个远程调用结束

@RestController
public class TestCountDownlatchController {
    
     @GetMapping("/order/{id}")
     public Map<String, Object> order(@PathVariable int id) {
         HashMap<String, Object> map = new HashMap<>();
         map.put("id", id);
         map.put("total", "2300.00");
         sleep(2000);
         return map;
     }
        
     @GetMapping("/product/{id}")
     public Map<String, Object> product(@PathVariable int id) {
         HashMap<String, Object> map = new HashMap<>();
         if (id == 1) {
             map.put("name", "小爱音箱");
             map.put("price", 300);
         } else if (id == 2) {
             map.put("name", "小米手机");
             map.put("price", 2000);
         }
         map.put("id", id);
         sleep(1000);
         return map;
     }

     @GetMapping("/logistics/{id}")
     public Map<String, Object> logistics(@PathVariable int id) {
         HashMap<String, Object> map = new HashMap<>();
         map.put("id", id);
         map.put("name", "中通快递");
         sleep(2500);
         return map;
     }

    
     private void sleep(int millis) {
         try {
             Thread.sleep(millis);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
}

rest 远程调用

RestTemplate restTemplate = new RestTemplate();
log.debug("begin");
ExecutorService service = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(4);

Future<Map<String,Object>> f1 = service.submit(() -> {
    Map<String, Object> r =
    restTemplate.getForObject("http://localhost:8080/order/{1}", Map.class, 1);
    return r;
});

Future<Map<String, Object>> f2 = service.submit(() -> {
    Map<String, Object> r =
    restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 1);
    return r;
});

Future<Map<String, Object>> f3 = service.submit(() -> {
    Map<String, Object> r =
    restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 2);
    return r;
});

Future<Map<String, Object>> f4 = service.submit(() -> {
    Map<String, Object> r =
    restTemplate.getForObject("http://localhost:8080/logistics/{1}", Map.class, 1);
    return r;
});

System.out.println(f1.get());
System.out.println(f2.get());
System.out.println(f3.get());
System.out.println(f4.get());
log.debug("执行完毕");
service.shutdown();

执行结果

19:51:39.711 c.TestCountDownLatch [main] - begin 
{total=2300.00, id=1} 
{price=300, name=小爱音箱, id=1} 
{price=2000, name=小米手机, id=2} 
{name=中通快递, id=1} 
19:51:42.407 c.TestCountDownLatch [main] - 执行完毕
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值