JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段

Posted Z && Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段相关的知识,希望对你有一定的参考价值。

1. 等待多个线程准备完毕(\\r可以覆盖上次的打印内)

玩王者荣耀时,有十个玩家(相当于十个线程),只有等这十个玩家的进度条都为100%时才会开始游戏,现在我们使用CountdownLarch倒计时锁模拟这个过程

示例代码:

package com.tian;

import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j(topic = "c.TestCountDownLatch")
public class TestCountDownLatch {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        test2();
    }

    private static void test2() throws InterruptedException {
        AtomicInteger num = new AtomicInteger(0);
        ExecutorService service = Executors.newFixedThreadPool(10, (r) -> {
            return new Thread(r, "t" + num.getAndIncrement());
        });
        // 初始倒计时为10
        CountDownLatch latch = new CountDownLatch(10);
        String[] all = new String[10];
        Random r = new Random();
        for (int j = 0; j < 10; j++) {
            int x = j;
            service.submit(() -> {
                for (int i = 0; i <= 100; i++) {
                    try {
                        Thread.sleep(r.nextInt(100));
                    } catch (InterruptedException e) {
                    }
                    all[x] = Thread.currentThread().getName() + "(" + (i + "%") + ")";
                    System.out.print("\\r" + Arrays.toString(all));
                }
                // 每次有一个线程到达100% 倒计时减1
                latch.countDown();
            });
        }
        // 等待倒计时为0
        latch.await();
        System.out.println("\\n游戏开始...");
        service.shutdown();
    }
}

运行结果:


2. 等待多个远程调用结束

线程Controller需要等待接口调用成功后才会执行下面的逻辑,怎么保证
多个远程调用结束结束呢?下面介绍2种方法。


2.1 需要返回结果 使用Future

    private static void test3() throws InterruptedException, ExecutionException {
        RestTemplate restTemplate = new RestTemplate();
        log.debug("begin");
        ExecutorService service = Executors.newCachedThreadPool();

        Future<Map<String, Object>> f1 = service.submit(() -> {
            return restTemplate.getForObject("http://localhost:8080/order/{1}", Map.class, 1);
        });
        Future<Map<String, Object>> f2 = service.submit(() -> {
            return restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 1);
        });
        // 等待线程1的结果 阻塞在这里
        System.out.println(f1.get());
        // 等待线程2的结果 阻塞在这里
        System.out.println(f2.get());
        // 执行到这里时 已经成功获取到f1和f2的结果了
        log.debug("执行完毕");
        service.shutdown();
    }

2.2 不需要返回值结果 使用CountdownLatch

    private static void test3() throws InterruptedException, ExecutionException {
        RestTemplate restTemplate = new RestTemplate();
        log.debug("begin");
        ExecutorService service = Executors.newCachedThreadPool();
        // 初始倒计时为2
        CountDownLatch latch = new CountDownLatch(2);
        service.submit(() -> {
            Map<String, Object> response = restTemplate.getForObject("http://localhost:8080/order/{1}", Map.class, 1);
            // 倒计时减1
            latch.countDown();
        });
        service.submit(() -> {
            Map<String, Object> response1 = restTemplate.getForObject("http://localhost:8080/product/{1}", Map.class, 1);
            // 倒计时减1
            latch.countDown();
        });
        // 等待倒计时为0
        latch.await();
        log.debug("执行完毕");
        service.shutdown();
    }


以上是关于JUC并发编程 共享模式之工具 JUC CountdownLatch(倒计时锁) -- CountdownLatch应用(等待多个线程准备完毕( 可以覆盖上次的打印内)等待多个远程调用结束)(代码片段的主要内容,如果未能解决你的问题,请参考以下文章

JUC并发编程 共享模式之工具 JUC Semaphore(信号量) -- 介绍 & 使用

JUC并发编程 共享模式之工具 JUC ConcurrentHashMap -- ConcurrentHashMap的错误使用和正确使用(示例:统计单词个数)

JUC并发编程 共享模式之工具 JUC Semaphore(信号量) -- Semaphore原理

JUC并发编程 共享模式之工具 JUC 线程安全的集合类 -- 线程安全的集合类概述

JUC并发编程 共享模式之工具 ThreadPoolExecutor -- 正确处理线程池异常

JUC并发编程 共享模式之工具 JUC 读写锁 ReentrantReadWriteLock -- ReentrantReadWriteLock(不可重入锁)使用 & 注意事项