Java并发工具类的使用 2022-02-28 14:42 131阅读 0赞 在JDK中的`java.util.concurrent`包里提供了几个实用的并发工具类,下面我们一起来了解下。 ### CountDownLatch ### **功能:** CountDownLatch允许一个或多个线程等待其他线程完成操作 我们来看一个查询航班的例子,用户访问APP,查询北京到上海的航班信息,后台需要同时调用三家航空公司提供的API查询数据,最后将最终查询结果汇总后返回。 ![查询航班信息][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h6eWdjcw_size_16_color_FFFFFF_t_70] **示例代码如下:** public class FlightQueryDemo { private static List<String> company = Arrays.asList("中国国际航空", "东方航空", "海南航空"); private static List<String> flightList = new ArrayList<>(); public static void main(String[] args) { String origin = "BJ"; String dest = "SH"; Thread[] th = new Thread[company.size()]; CountDownLatch cdl = new CountDownLatch(3); for (int i = 0; i < 3; i++) { String name = company.get(i); th[i] = new Thread(() -> { System.out.printf("%s 查询从%s到%s的机票信息\n", name, origin, dest); // 随机产生票数 int val = new Random().nextInt(10); try { TimeUnit.SECONDS.sleep(val); } catch (InterruptedException e) { e.printStackTrace(); } flightList.add(name + "----" + val); System.out.printf("%s公司查询成功!\n", name); cdl.countDown(); }); th[i].start(); } try { cdl.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("==============查询结果如下:================"); flightList.forEach(System.out::println); } } CountDownLatch的构造函数接收一个int类型的参数作为计数器,调用CountDownLatch的`countDown()`方法时,计数器就会减一,CountDownLatch的`await()`方法会阻塞当前线程,直到计数器变为零。 > 注意:计数器必须大于等于0,另外CountDownLatch不可能重新初始化或者修改CountDownLatch对象的内部计数器的值。 ### CyclicBarrier ### **功能:** 让一组线程到达一个屏障(同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续运行。 我们来看一个运动员赛跑的例子,所有运动员准备好后一起开始起跑。 **示例代码如下:** public class RaceDemo { public static void main(String[] args) { CyclicBarrier barrier = new CyclicBarrier(8); Thread[] sportsman = new Thread[8]; for (int i = 0; i < 8; i++) { sportsman[i] = new Thread(() -> { try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); System.out.println(Thread.currentThread().getName() + "准备好了"); barrier.await(); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } System.out.println("选手" + Thread.currentThread().getName() + "起跑"); }, "paly[" + i + "]"); sportsman[i].start(); } } } CyclicBarrier默认的构造方法是`CyclicBarrier(int parties)`,其参数表示屏障拦截的线程数量,每个线程调用`await()`方法告诉CyclicBarrier我已经到达了屏障,然后当前线程被阻塞。 CyclicBarrier还有一个构造函数`CyclicBarrier(int parties, Runnable barrierAction)`,用于在线程到达屏障时,优先执行barrierAction,这里不再演示。 #### CyclicBarrier和CountDownLatch的区别 #### CountDownLatch的计数器只能使用一次,二CyclicBarrier的计数器可以使用`reset()`方法重置。所以CyclicBarrier能处理更为复杂的业务场景。例如,如果执行过程中发生问题,可以重置计数器,并让线程重新执行一次。 ### Semaphore ### **功能:** Semaphore是用来控制同时访问特定资源的线程数量,它通过协调各个线程,比保证合理的使用公共资源。 我们来看一个停车场停车的例子,停车场停满后,其它车就需要在停车场外等待,直到有车从停车场离开,空出位置,外面的车子才可以进来。 **示例代码如下:** public class SemaphoreDemo { public static void main(String[] args) { Semaphore semaphore = new Semaphore(5); Thread[] car = new Thread[10]; for (int i = 0; i < 10; i++) { car[i] = new Thread(() -> { try { semaphore.acquire(); System.out.println(Thread.currentThread().getName() + "可以进停车场"); } catch (InterruptedException e) { e.printStackTrace(); } try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); // System.out.println(Thread.currentThread().getName() + "停车时间:" + new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } semaphore.release(); System.out.println(Thread.currentThread().getName() + "离开停车场"); }, "car[" + i + "]"); car[i].start(); } } } ### Exchanger ### **功能:** Exchanger是一个用于线程间协作的工具类。Exchanger用于进行线程间的数据交换。 我们来看一个校对工作的例子,例如:银行将纸质的资金流水通过人工的方式录入成电子银行流水,为了避免错误,采用AB两人同时进行录入,录入完成后需要对这两人录入的结果进行比较,看看是否录入一致。 **示例代码如下:** public class ExchangerDemo { private static final Exchanger<String> exgr = new Exchanger<String>(); private static ExecutorService pool = Executors.newFixedThreadPool(2); public static void main(String[] args) { pool.execute(new Runnable() { @Override public void run() { try { String A = "统计结果A"; exgr.exchange(A); } catch (InterruptedException e) { e.printStackTrace(); } } }); pool.execute(new Runnable() { @Override public void run() { try { String B = "统计结果B"; String A = exgr.exchange(B); System.out.println("A和B的数据是否一致:" + A.equals(B) + ", A录入的是:" + A + ", B录入的是:" + B); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } 如果两个线程有一个没有执行`exchanger()`方法,则会一直等待。为了避免一直等待,可以使用`exchange(V x, long timeout, TimeUnit unit)`设置最大等待时长。 ### 总结 ### 本文一共介绍了四个常用的并发工具类,每个都有其特定的使用场景,后面如果遇到类似的场景问题不妨试一试这些工具类。 **参考:** Java并发编程的艺术 方腾飞 魏鹏 程晓明 著 -------------------- \------------本文结束感谢您的阅读------------ [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h6eWdjcw_size_16_color_FFFFFF_t_70]: /images/20220228/d3e28864623043e9bb741f06d9d97003.png
相关 彻底理解Java并发:Java并发工具类 > 本篇内容包括:Java 并发工具类的介绍、使用方式与 Demo,包括了 CountDownLatch(线程计数器)、CyclicBarrier(回环栅栏)、Semaphor 布满荆棘的人生/ 2023年09月23日 13:07/ 0 赞/ 13 阅读
相关 Java中的并发工具类 等待多线程完成的 CountDownLatch CountDownLatch 允许一个或多个线程等待其他线程完成操作。 需求:我们需要解析一个 Exc ゞ 浴缸里的玫瑰/ 2022年05月28日 08:41/ 0 赞/ 108 阅读
相关 温习 Java 常见的并发工具类 对着书敲一遍,温故而知新 CountDownLatch,CyclicBarrier,Semaphore,Exchanger CountDownLatch p 水深无声/ 2022年05月28日 06:57/ 0 赞/ 56 阅读
相关 Java并发——同步工具类 在java 1.5中,提供了一些非常有用的辅助类来帮助我们进行并发编程,比如CountDownLatch,CyclicBarrier和Semaphore 同步工具类包括信号量 超、凢脫俗/ 2022年05月18日 08:56/ 0 赞/ 162 阅读
相关 java中的并发工具类 Semaphore与Exchanger ![这里写图片描述][70] [70]: /images/20220517/1e3e4fd0a9b04cdd944c2a503b 旧城等待,/ 2022年05月17日 05:17/ 0 赞/ 97 阅读
相关 Java并发工具类 在Java1.5中,提供了一些很有用的辅助类来帮助我们进行并发编程,比如CountDownLatch\[计数器\],CyclicBarrier\[循环屏障\],Semaphor 迈不过友情╰/ 2022年05月08日 13:24/ 0 赞/ 157 阅读
相关 Java并发工具类Phaser Phaser由java7中推出,是Java SE 7中新增的一个使用同步工具,在功能上面它与[CyclicBarrier][]、[CountDownLatch][]有些重叠,但 忘是亡心i/ 2022年04月04日 03:22/ 0 赞/ 150 阅读
相关 Java并发工具类的使用 在JDK中的`java.util.concurrent`包里提供了几个实用的并发工具类,下面我们一起来了解下。 CountDownLatch 功能: CountDown 我会带着你远行/ 2022年02月28日 14:42/ 0 赞/ 132 阅读
相关 Java 中的并发工具类 From: [https://blog.wuwii.com/juc-utils.html][https_blog.wuwii.com_juc-utils.html] `jav Dear 丶/ 2022年02月25日 19:44/ 0 赞/ 151 阅读
相关 Java并发工具类 - CountDownLatch 一.CountDownLatch用法 1、简介 CountDownLatch是Java1.5之后引入的Java并发工具类,放在java.util.concurr 电玩女神/ 2022年01月23日 09:01/ 0 赞/ 152 阅读
还没有评论,来说两句吧...