Java使用CountDownLatch实现网络同步请求的示例代码
抓手 人气:0CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步,它能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。
这里是使用CountDownLatch和多线程完成商品信息异步组装:
import java.time.LocalDateTime; import java.util.StringJoiner; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author 向振华 * @date 2023/01/04 14:01 */ public class Test { public static void main(String[] args) { // 创建线程池 ExecutorService executorService = Executors.newFixedThreadPool(10); CountDownLatch countDownLatch = new CountDownLatch(3); System.out.println("开始 " + LocalDateTime.now()); StringJoiner sj = new StringJoiner("、"); // 线程1 executorService.execute(() -> { try { String do1 = do1(); sj.add(do1); } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } }); // 线程2 executorService.execute(() -> { try { String do2 = do2(); sj.add(do2); } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } }); // 线程3 executorService.execute(() -> { try { String do3 = do3(); sj.add(do3); } catch (Exception e) { e.printStackTrace(); } finally { countDownLatch.countDown(); } }); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(sj.toString()); System.out.println("完成 " + LocalDateTime.now()); } private static String do1() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("1查询商品规格信息"); return "商品规格"; } private static String do2() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("2查询商品价格信息"); return "商品价格"; } private static String do3() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("3查询商品图片信息"); return "商品图片"; } }
输出结果:
开始 2023-01-04T14:16:40.441
1查询商品规格信息
3查询商品图片信息
2查询商品价格信息
商品规格、商品图片、商品价格
完成 2023-01-04T14:16:45.468
知识补充
1.背景
- countDownLatch是在java1.5被引入,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。
- 存在于java.util.cucurrent包下
2.概念
countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。
3.源码
countDownLatch类中只提供了一个构造器:
//参数count为计数值 public CountDownLatch(int count) { };
类中有三个方法是最重要的:
//调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行 public void await() throws InterruptedException { }; //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行 public boolean await(long timeout, TimeUnit unit) throws InterruptedException { }; //将count值减1 public void countDown() { };
4.示例
普通示例
public class CountDownLatchTest { public static void main(String[] args) { final CountDownLatch latch = new CountDownLatch(2); System.out.println("主线程开始执行…… ……"); //第一个子线程执行 ExecutorService es1 = Executors.newSingleThreadExecutor(); es1.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); System.out.println("子线程:"+Thread.currentThread().getName()+"执行"); } catch (InterruptedException e) { e.printStackTrace(); } latch.countDown(); } }); es1.shutdown(); //第二个子线程执行 ExecutorService es2 = Executors.newSingleThreadExecutor(); es2.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("子线程:"+Thread.currentThread().getName()+"执行"); latch.countDown(); } }); es2.shutdown(); System.out.println("等待两个线程执行完毕…… ……"); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("两个子线程都执行完毕,继续执行主线程"); } }
结果集:
主线程开始执行…… ……
等待两个线程执行完毕…… ……
子线程:pool-1-thread-1执行
子线程:pool-2-thread-1执行
两个子线程都执行完毕,继续执行主线程
加载全部内容