当前位置:   article > 正文

掌握Guava的并发工具:轻松应对复杂并发场景_guava并发工具类

guava并发工具类

推荐语

这篇文章介绍了 Guava 的一些常用并发工具类的使用方法。通过学习这些工具类,我们可以轻松地处理异步操作。这些工具类不仅功能丰富,还大大简化并发编程的复杂性。无论你是初学者还是经验丰富的开发者,这篇文章都会对你在并发编程方面有所帮助。

关于Guava的并发工具

Guava提供了一些丰富的并发工具,帮助开发者更好地处理并发编程中的问题。例如,Guava提供了ListenableFuture、CountDownLatch、CyclicBarrier等工具。这些工具对Java并发包(java.util.concurrent)进行了扩展,使其功能更强大,使用更方便。

具体来说,其中ListenableFuture是Guava对Java Future的扩展,它允许你注册回调函数,当Future的计算结果可用时,这个回调函数会被执行。CountDownLatch和CyclicBarrier则是用于同步的工具类,它们可以让一组线程等待彼此,然后再一起执行。

Guava的并发工具盘点

Guava提供的并发工具当然不仅仅只有ListenableFuture、CountDownLatch、CyclicBarrier等,还有很多其他的,博主这里算是抛砖引玉吧,把我用过的,我认为比较好用的,在这里给大家梳理总结一下,如果大家用到了其他更好用的,欢迎在评论区告诉,一起深入交流。那么本篇文章的主角就是ListenableFuture、CountDownLatch和CyclicBarrier,那么下面先简单的盘一下这几个类的功能特性:

  • ListenableFuture:它是Guava对JDK的Future接口的扩展。相比于传统的Future,ListenableFuture允许你注册一个回调函数,一旦计算完成,这个回调函数就会被执行。这使得ListenableFuture在处理异步计算的结果时提供了更大的灵活性。
  • CountDownLatch:这是Java中的一个并发工具类,用于协调多个线程之间的同步。CountDownLatch能够使一个线程等待其他线程完成各自的工作后再执行。例如,你可以使用CountDownLatch来确保在继续执行主线程之前,一组工作线程已经完成了它们的初始化工作。
  • CyclicBarrier:这是Java中的一个同步工具类。CyclicBarrier可以让一组线程互相等待,直到所有线程都达到某个状态后再一起执行。这在并行计算中特别有用,例如,你可能想要在所有线程都完成了它们的一部分计算后,再进行一次汇总操作。CyclicBarrier可以确保所有线程都在同一时间点进行这个汇总操作。

环境配置

目前maven中央仓库的最新版本是32.1.3-jre,本篇文章的所有示例也是基于这个版本:

  1. <dependency>
  2. <groupId>com.google.guava</groupId>
  3. <artifactId>guava</artifactId>
  4. <version>32.1.3-jre</version>
  5. </dependency>

Guava的并发工具如何使用

ListenableFuture

Guava类库的ListenableFuture是一个强大的工具,它扩展了Java的Future接口,增加了注册回调函数的功能。下面是一个使用Guava的ListenableFuture的示例:

  1. public class ListenableFutureExample {
  2. public static void main(String[] args) {
  3. ExecutorService executorService = Executors.newSingleThreadExecutor();
  4. ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
  5. ListenableFuture<String> future = listeningExecutorService.submit(new Callable<String>() {
  6. @Override
  7. public String call() throws Exception {
  8. // 模拟异步任务
  9. Thread.sleep(2000);
  10. System.out.println(Thread.currentThread().getName() + ":异步任务执行完毕");
  11. return "异步任务执行成功:success";
  12. }
  13. });
  14. Futures.addCallback(future, new FutureCallback<String>() {
  15. @Override
  16. public void onSuccess(String result) {
  17. // 异步任务执行成功后的回调方法
  18. System.out.println(Thread.currentThread().getName() + ":异步任务执行成功,结果是:" + result);
  19. listeningExecutorService.shutdown();//收到回调结果后,建议关注线程池,否则监听回调程序会一直阻塞,不会结束;
  20. }
  21. @Override
  22. public void onFailure(Throwable t) {
  23. // 异步任务执行失败后的回调方法
  24. System.out.println("异步任务执行失败");
  25. t.printStackTrace();
  26. }
  27. }, executorService);
  28. System.out.println(Thread.currentThread().getName() + ":主线程继续执行其他任务...");
  29. }
  30. }

在上面这个示例中,我们使用了Guava的ListeningExecutorService来创建一个线程池,并通过submit方法提交了一个异步任务。该异步任务模拟了一个耗时操作,等待2秒后返回结果。然后,我们使用Futures.addCallback方法为ListenableFuture对象注册了一个回调函数。当异步任务执行成功时,会调用onSuccess方法,并打印出异步任务的结果;当异步任务执行失败时,会调用onFailure方法,并打印出异常信息。最后,主线程继续执行其他任务。需要注意的是:在这里我关闭了线程池,否则监听回调程序会一直阻塞,不会结束;

CountDownLatch

在下面这个示例中,我们使用了Guava类库的Uninterruptibles.awaitUninterruptibly()方法来等待CountDownLatch的计数器变为0。这与使用Java标准库中的latch.await()方法类似,但Guava提供的方法能够更优雅地处理中断。其余部分与之前的示例相同,创建了多个工作线程,并使用CountDownLatch来协调它们的执行。当所有工作线程都调用latch.countDown()方法后,计数器将变为0,然后主线程通过Uninterruptibles.awaitUninterruptibly(latch)等待所有工作线程执行完毕,并输出"All worker threads have finished."。

  1. public class GuavaCountDownLatchExample {
  2. public static void main(String[] args) {
  3. int numberOfThreads = 3;
  4. CountDownLatch latch = new CountDownLatch(numberOfThreads);
  5. for (int i = 0; i < numberOfThreads; i++) {
  6. new Thread(new Worker(latch), "Thread" + i).start();
  7. }
  8. Uninterruptibles.awaitUninterruptibly(latch); // 使用Guava的Uninterruptibles类等待所有工作线程执行完毕
  9. System.out.println("All worker threads have finished.");
  10. }
  11. }
  12. class Worker implements Runnable {
  13. private final CountDownLatch latch;
  14. Worker(CountDownLatch latch) {
  15. this.latch = latch;
  16. }
  17. @Override
  18. public void run() {
  19. try {
  20. System.out.println(Thread.currentThread().getName() + " is working.");
  21. Thread.sleep((long) (Math.random() * 1000)); // 模拟工作线程执行的任务
  22. System.out.println(Thread.currentThread().getName() + " has finished.");
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. } finally {
  26. latch.countDown(); // 工作线程完成任务后,计数器减一
  27. }
  28. }
  29. }

CyclicBarrier

在 Guava 类库中,没有直接提供 CyclicBarrier 类。CyclicBarrier 是 Java 标准库中的一个类,它可以用于多线程间的同步。这里也简单梳理一下他的用法,因为在做多线程间同步协调的相关业务时,CountDownLatch和CyclicBarrier,是两个绕不过去的选项,这里放在一起也好作个对比。

在下面这个示例中,创建了10个工作线程,每个线程都执行相同的任务。这些线程通过CyclicBarrier进行同步,确保所有线程都达到屏障点(即调用cyclicBarrier.await()方法)后再一起继续执行。当所有线程都调用cyclicBarrier.await()方法后,屏障会被打破,所有线程可以继续执行后续的任务。在这个示例中,后续的任务是输出线程名称和"is running"的消息。

  1. public class CyclicBarrierExample {
  2. public static void main(String[] args) {
  3. final int totalThread = 10;
  4. CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread);
  5. for (int i = 0; i < totalThread; i++) {
  6. new Thread(new Task(cyclicBarrier), "Thread" + i).start();
  7. }
  8. }
  9. }
  10. class Task implements Runnable {
  11. private CyclicBarrier cyclicBarrier;
  12. public Task(CyclicBarrier cyclicBarrier) {
  13. this.cyclicBarrier = cyclicBarrier;
  14. }
  15. @Override
  16. public void run() {
  17. System.out.println(Thread.currentThread().getName() + " is ready");
  18. try {
  19. cyclicBarrier.await(); //等待其他线程到达屏障点
  20. } catch (Exception e) {
  21. e.printStackTrace();
  22. }
  23. System.out.println(Thread.currentThread().getName() + " is running");
  24. }
  25. }

写在最后

希望这篇文章能够为你提供有关 Guava 的 并发工具类的使用方法,让你在处理异步任务时能够更加得心应手。如果你觉得这篇文章对你有所帮助,不妨点个赞并分享给你的朋友。同时,欢迎关注我的公众号(凡夫编程)/博客(凡夫贬夫),获取更多关于技术知识和实用工具的分享。你的支持是我们创作的动力,也是我们分享更多优质内容的动力。谢谢!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/224972
推荐阅读
相关标签
  

闽ICP备14008679号