关于并发方面,juc已帮我们提供了很多好用的工具,而谷歌在此基础上做了扩展,使并发更容易,这些工具放在guava.jar包中。

本文演示几个简单的案例,见一下guava的效果。

guava maven配置

<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>27.0-jre</version>
</dependency>

guava中常用几个类

MoreExecutors:提供了一些静态方法,是对juc中的Executors类的一个扩展

Future:也提供了很多静态方法,是对juc中Future的一个扩展

案例1:异步执行任务完毕之后回调

public class Demo1 {public static void main(String[] args) throws ExecutionException, InterruptedException {//创建一个线程池ExecutorService executorService = Executors.newFixedThreadPool(5);ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);try {ListenableFuture<Integer> listenableFuture = listeningExecutorService.submit(() -> {System.out.println(System.currentTimeMillis());//休眠2秒,默认耗时TimeUnit.SECONDS.sleep(2);System.out.println(System.currentTimeMillis());return 10;});listenableFuture.addListener(()->{System.out.println("回调");},MoreExecutors.directExecutor());System.out.println(listenableFuture.get());}finally {listeningExecutorService.shutdown();}}
}

输出:

1608615858082
1608615860082
回调
10

另外一种写法:

public class Demo2 {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService delegate = Executors.newFixedThreadPool(5);try {ListeningExecutorService executorService = MoreExecutors.listeningDecorator(delegate);ListenableFuture<Integer> submit = executorService.submit(() -> {System.out.println(System.currentTimeMillis());TimeUnit.SECONDS.sleep(4);int i = 10 / 0;System.out.println(System.currentTimeMillis());return 10;});Futures.addCallback(submit, new FutureCallback<Integer>() {@Overridepublic void onSuccess(@Nullable Integer result) {System.out.println("执行成功" + result);}@Overridepublic void onFailure(Throwable t) {try {TimeUnit.MILLISECONDS.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("执行任务发生异常:" + t.getMessage());}}, MoreExecutors.directExecutor());System.out.println(submit.get());} finally {delegate.shutdown();}}
}

输出:

1608615899714
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zeroat com.google.common.util.concurrent.AbstractFuture.getDoneValue(AbstractFuture.java:552)at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture.java:533)at com.google.common.util.concurrent.FluentFuture$TrustedFuture.get(FluentFuture.java:82)at com.example.thread.guava.Demo2.main(Demo2.java:40)
Caused by: java.lang.ArithmeticException: / by zeroat com.example.thread.guava.Demo2.lambda$main$0(Demo2.java:20)at com.google.common.util.concurrent.TrustedListenableFutureTask$TrustedFutureInterruptibleTask.runInterruptibly(TrustedListenableFutureTask.java:125)at com.google.common.util.concurrent.InterruptibleTask.run(InterruptibleTask.java:57)at com.google.common.util.concurrent.TrustedListenableFutureTask.run(TrustedListenableFutureTask.java:78)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)
执行任务发生异常:/ by zero

上面通过调用Futures的静态方法addCallback在异步执行的任务中添加回调,回调的对象是一个FutureCallback,此对象有2个方法,任务执行成功调用onSuccess,执行失败调用onFailure

示例2:获取一批异步任务的执行结果

@Slf4j
public class Demo3 {public static void main(String[] args) throws ExecutionException, InterruptedException {log.info("star");ExecutorService delegate = Executors.newFixedThreadPool(5);try {ListeningExecutorService executorService = MoreExecutors.listeningDecorator(delegate);List<ListenableFuture<Integer>> futureList = new ArrayList<>();for (int i = 5; i >= 0; i--) {int j = i;futureList.add(executorService.submit(() -> {TimeUnit.SECONDS.sleep(j);return j;}));}//获取一批任务的执行结果List<Integer> resultList = Futures.allAsList(futureList).get();//输出resultList.forEach(item -> {log.info("{}", item);});} finally {delegate.shutdown();}}
}
14:26:35.970 [main] INFO com.itsoku.chat34.Demo3 - star
14:26:41.137 [main] INFO com.itsoku.chat34.Demo3 - 5
14:26:41.138 [main] INFO com.itsoku.chat34.Demo3 - 4
14:26:41.138 [main] INFO com.itsoku.chat34.Demo3 - 3
14:26:41.138 [main] INFO com.itsoku.chat34.Demo3 - 2
14:26:41.138 [main] INFO com.itsoku.chat34.Demo3 - 1
14:26:41.138 [main] INFO com.itsoku.chat34.Demo3 - 0

结果中按顺序输出了6个异步任务的结果,此处用到了Futures.allAsList方法,看一下此方法的声明:

public static <V> ListenableFuture<List<V>> allAsList(Iterable<? extends ListenableFuture<? extends V>> futures)

传递一批ListenableFuture,返回一个ListenableFuture<List<V>>,内部将一批结果转换为了一个ListenableFuture对象。

示例3:一批任务异步执行完毕之后回调


@Slf4j
public class Demo4 {public static void main(String[] args) throws ExecutionException, InterruptedException {log.info("star");ExecutorService delegate = Executors.newFixedThreadPool(5);try {ListeningExecutorService executorService = MoreExecutors.listeningDecorator(delegate);List<ListenableFuture<Integer>> futureList = new ArrayList<>();for (int i = 5; i >= 0; i--) {int j = i;futureList.add(executorService.submit(() -> {TimeUnit.SECONDS.sleep(j);return j;}));}ListenableFuture<List<Integer>> listListenableFuture = Futures.allAsList(futureList);Futures.addCallback(listListenableFuture, new FutureCallback<List<Integer>>() {@Overridepublic void onSuccess(@Nullable List<Integer> result) {log.info("result中所有结果之和:" + result.stream().reduce(Integer::sum).get());}@Overridepublic void onFailure(Throwable t) {log.error("执行任务发生异常:" + t.getMessage(), t);}}, MoreExecutors.directExecutor());} finally {delegate.shutdown();}}
}

输出:

14:47:04.819 [main] INFO com.itsoku.chat34.Demo4 - star
14:47:09.933 [pool-1-thread-1] INFO com.itsoku.chat34.Demo4 - result中所有结果之和:15

代码中异步执行了一批任务,所有任务完成之后,回调了上面的onSuccess方法,内部对所有的结果进行sum操作。

总结

  • 通过guava提供的一些工具类,方便异步执行任务并进行回调

  • guava内部还有很多好用的工具类,有兴趣的可以去研究一下

24.线程系列- google提供的一些好用的并发工具类相关推荐

  1. 【kafka】google提供的一些好用的并发工具类

    1.概述 环境:jdk1.8. 关于并发方面的,juc已帮我们提供了很多好用的工具,而谷歌在此基础上做了扩展,使并发编程更容易,这些工具放在guava.jar包中. 本文演示几个简单的案例,见一下gu ...

  2. 并发工具类(四)两个线程进行数据交换的Exchanger

    简介 Exchanger(交换者)是一个用于线程间协作的工具类.Exchanger用于进行线程间的数据交换.它提供一个同步点,在这个同步点两个线程可以交换彼此的数据.这两个线程通过exchange方法 ...

  3. Java多线程系列(九):CountDownLatch、Semaphore等4大并发工具类详解

    之前谈过高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 ,以及高并发编程系列:ConcurrentHashMap的实现原理(JDK1.7和JDK1.8) 今天主要介绍concurre ...

  4. 【搞定Java并发编程】第24篇:Java中的并发工具类之CountDownLatch

    上一篇:Java中的阻塞队列 BlockingQueue 详解 本文目录: 1.CountDownLatch的基本概述 2.CountDownLatch的使用案例 3.CountDownLatch的源 ...

  5. j.u.c系列(11)---之并发工具类:Exchanger

    写在前面 前面三篇博客分别介绍了CyclicBarrier.CountDownLatch.Semaphore,现在介绍并发工具类中的最后一个Exchange.Exchange是最简单的也是最复杂的,简 ...

  6. 并发工具类(四)线程间的交换数据 Exchanger

    前言   JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...

  7. j.u.c系列(08)---之并发工具类:CountDownLatch

    写在前面 CountDownLatch所描述的是"在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待":用给定的计数 初始化 CountDownLatch.由于调 ...

  8. 线程池、volatile、原子性、并发工具类

    目录 线程状态 线程池-基本原理 线程池 - Executors默认线程池 线程池 - ThreadPoolExecutor 线程池参数-拒绝策略 volatile 原子性 原子性 - AtomicI ...

  9. 《Java并发编程的艺术》——Java中的并发工具类、线程池、Execute框架(笔记)

    文章目录 八.Java中的并发工具类 8.1 等待多线程完成的CountDownLatch 8.2 同步屏障CyclicBarrier 8.2.1 CyclicBarrier简介 8.2.2 Cycl ...

最新文章

  1. vue修改节点class_Vue2.0 源码解读系列 来自 Vue 的神秘礼盒
  2. Java对象间的转化
  3. Linux下ntpdate时间同步
  4. PHP中4个包含文件方法的差异
  5. Python collections的使用
  6. python 描述统计_Python统计学-004:描述统计-众数
  7. 在Linux和qt下安装EasyPr遇到的问题
  8. python漏洞扫描器编写_漏洞扫描器开发与设计的一点感悟
  9. JavaScript封装回调函数(委托)
  10. 共享租赁汽车,必将重新设计中国汽车产业链游戏规则
  11. Redis数据库常用命令(超级详细)
  12. NRF52840 SOC 在空气净化市场应用的发展趋势
  13. Python+班级管理系统 毕业设计-附源码171809
  14. Redhat7升级内核(含安装yum)
  15. OSChina 周二乱弹 ——追妹子最管用的方式
  16. java sleep唤醒_详解Java中的线程让步yield()与线程休眠sleep()方法
  17. 多功能在线起名取名查重工具微信小程序源码 可开流量主 带安装教程
  18. 拨号上网怎么修改dns服务器,dns怎么设置才能上网 dns设置上网方法【图文】
  19. 全文索引JAVA_全文索引Sphinx和sphinx的中文分词
  20. c语言判断闰年星期几,C语言判断闰年

热门文章

  1. html中调用js带参数传递,JS传参技巧总结
  2. 努力学Java挣小钱钱
  3. E. Pencils and Boxes(划窗+dp+树状数组)
  4. 菜鸟程序员试用期必备法则
  5. 1951. 宇宙人浇花(最大异或对变形)
  6. SQL数据库脚本操作(WINCC VBS脚本)
  7. 智能车竞赛技术报告 |单车拉力组 - 大理工大学- 基于串级控制的智能循迹自形成研究
  8. 磁场强度切向分量连续性证明
  9. 仿百度网盘的一款轻量级微服务架构网盘系统
  10. 【原创】数据分析报告撰写概览