Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
Java高并发教程
-> 谷歌提供的一些好用的并发工具类
1、必须知道的几个概念
2、并发级别
3、有关并行的两个重要定律
4、JMM相关的一些概念
5、深入理解进程和线程
6、线程的基本操作
7、volatile与Java内存模型
8、线程组
9、用户线程和守护线程
10、线程安全和synchronized
11、中断线程的几种方式
12、JUC中ReentrantLock
13、JUC中的Condition
14、JUC中的LockSupport工具类
15、UC中的Semaphore(信号量)
16、JUC中的CountDownLatch
17、JUC中的循环栅栏CyclicBarrier
18、线程池
19、JUC中的Executor框架详解1
20、JUC中的Executor框架详解2
21、java中的CAS
22、java中的UnSafe类
23、JUC中的原子操作类
24、ThreadLocal、InheritableThreadLocal
25、JUC中的阻塞队列
26、JUC中一些常见的集合
27、实战:你的接口太慢了需要优化
28、实战:构建日志系统
29、实战:一起来搞懂限流
30、JUC中的CompletableFuture
31、等待线程完成的方式你知道几种?
32、原子操作增强类LongAdder、LongAccumulator
33、怎么演示公平锁和非公平锁
34、谷歌提供的一些好用的并发工具类
35、延迟队列 DelayQueue 详解
36、线程6种状态详解
37、如何实现一个通用的延迟队列?
上一篇:怎么演示公平锁和非公平锁
下一篇:延迟队列 DelayQueue 详解
<div style="display:none"></div> 关于并发方面的,juc已帮我们提供了很多好用的工具,而谷歌在此基础上做了扩展,使并发编程更容易,这些工具放在guava.jar包中。 本文演示几个简单的案例,见一下guava的效果。 ## guava maven配置 ```java <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.0-jre</version> </dependency> ``` ## guava中常用几个类 **MoreExecutors**:提供了一些静态方法,是对juc中的Executors类的一个扩展。 **Futures**:也提供了很多静态方法,是对juc中Future的一个扩展。 ## 案例1:异步执行任务完毕之后回调 ```java package com.itsoku.chat34; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 跟着阿里p7学并发,微信公众号:javacode2018 */ @Slf4j public class Demo1 { 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(() -> { log.info("{}", System.currentTimeMillis()); //休眠2秒,默认耗时 TimeUnit.SECONDS.sleep(2); log.info("{}", System.currentTimeMillis()); return 10; }); //当任务执行完毕之后回调对应的方法 submit.addListener(() -> { log.info("任务执行完毕了,我被回调了"); }, MoreExecutors.directExecutor()); log.info("{}", submit.get()); } finally { delegate.shutdown(); } } } ``` 输出: ```java 14:25:50.055 [pool-1-thread-1] INFO com.itsoku.chat34.Demo1 - 1567491950047 14:25:52.063 [pool-1-thread-1] INFO com.itsoku.chat34.Demo1 - 1567491952063 14:25:52.064 [pool-1-thread-1] INFO com.itsoku.chat34.Demo1 - 任务执行完毕了,我被回调了 14:25:52.064 [main] INFO com.itsoku.chat34.Demo1 - 10 ``` **说明:** `ListeningExecutorService`接口继承于juc中的`ExecutorService`接口,对`ExecutorService`做了一些扩展,看其名字中带有Listening,说明这个接口自带监听的功能,可以监听异步执行任务的结果。通过`MoreExecutors.listeningDecorator`创建一个`ListeningExecutorService`对象,需传递一个`ExecutorService`参数,传递的`ExecutorService`负责异步执行任务。 `ListeningExecutorService`的`submit`方法用来异步执行一个任务,返回`ListenableFuture`,`ListenableFuture`接口继承于juc中的`Future`接口,对`Future`做了扩展,使其带有监听的功能。调用`submit.addListener`可以在执行的任务上添加监听器,当任务执行完毕之后会回调这个监听器中的方法。 `ListenableFuture`的`get`方法会阻塞当前线程直到任务执行完毕。 上面的还有一种写法,如下: ```java package com.itsoku.chat34; import com.google.common.util.concurrent.*; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 跟着阿里p7学并发,微信公众号:javacode2018 */ @Slf4j 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(() -> { log.info("{}", System.currentTimeMillis()); TimeUnit.SECONDS.sleep(4); //int i = 10 / 0; log.info("{}", System.currentTimeMillis()); return 10; }); Futures.addCallback(submit, new FutureCallback<Integer>() { @Override public void onSuccess(@Nullable Integer result) { log.info("执行成功:{}", result); } @Override public void onFailure(Throwable t) { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } log.error("执行任务发生异常:" + t.getMessage(), t); } }, MoreExecutors.directExecutor()); log.info("{}", submit.get()); } finally { delegate.shutdown(); } } } ``` 输出: ```java 14:26:07.938 [pool-1-thread-1] INFO com.itsoku.chat34.Demo2 - 1567491967936 14:26:11.944 [pool-1-thread-1] INFO com.itsoku.chat34.Demo2 - 1567491971944 14:26:11.945 [main] INFO com.itsoku.chat34.Demo2 - 10 14:26:11.945 [pool-1-thread-1] INFO com.itsoku.chat34.Demo2 - 执行成功:10 ``` 上面通过调用`Futures`的静态方法`addCallback`在异步执行的任务中添加回调,回调的对象是一个`FutureCallback`,此对象有2个方法,任务执行成功调用`onSuccess`,执行失败调用`onFailure`。 失败的情况可以将代码中`int i = 10 / 0;`注释去掉,执行一下可以看看效果。 ## 示例2:获取一批异步任务的执行结果 ```java package com.itsoku.chat34; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; import java.util.stream.Collectors; /** * 跟着阿里p7学并发,微信公众号:javacode2018 */ @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(); } } } ``` 输出: ```java 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`方法,看一下此方法的声明: ```java public static <V> ListenableFuture<List<V>> allAsList( Iterable<? extends ListenableFuture<? extends V>> futures) ``` 传递一批`ListenableFuture`,返回一个`ListenableFuture<List<V>>`,内部将一批结果转换为了一个`ListenableFuture`对象。 ## 示例3:一批任务异步执行完毕之后回调 异步执行一批任务,最后技术其和 ```java package com.itsoku.chat34; import com.google.common.util.concurrent.*; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.nullness.qual.Nullable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 跟着阿里p7学并发,微信公众号:javacode2018 */ @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>>() { @Override public void onSuccess(@Nullable List<Integer> result) { log.info("result中所有结果之和:" + result.stream().reduce(Integer::sum).get()); } @Override public void onFailure(Throwable t) { log.error("执行任务发生异常:" + t.getMessage(), t); } }, MoreExecutors.directExecutor()); } finally { delegate.shutdown(); } } } ``` 输出: ```java 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内部还有很多好用的工具类,有兴趣的可以去研究一下 <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
#custom-toc-container