GuavaFuture 有回调函数的Future使用demo

  谷歌的 guava 工具包和 hutool 的工具包是目前比较全而且好用的java开发工具包可以避免我们重复造轮子,最近看了下Guava的ListenableFutrue可以在线程任务执行完成之后执行我们自己编写的回调函数,从而避免了get()方法的阻塞,感觉不错,记录一下。

  本示例使用maven作为jar包管理工具,首先在pom文件中引入guava工具包,代码如下:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
   <version>xxx</version> </dependency>

PS: hutool 工具包引入示例:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.2.0</version>
</dependency>

        首先讲一下简单的业务逻辑: 这是一个阳光明媚的早上,小明在学习编程,然后他想喝茶了。就跟管家说,你好Jenkins我想喝茶。然后就有两个仆人去做事儿了,一个人洗茶杯一个人烧水,小明继续学习。茶杯洗完了仆人会告诉小明然后把茶杯端过来,水烧开了仆人也告诉小明,把热水壶拎过来。小明暂停学习然后去快乐地泡茶喝茶。然而,仆人可能在工作的过程中出岔子,其结果也会告知小明,小明只能放弃喝茶。以下是实现代码:

  

  1 package com.vincent.fat.core.juc;
  2 
  3 import cn.hutool.core.util.RandomUtil;
  4 import com.google.common.util.concurrent.*;
  5 import lombok.extern.slf4j.Slf4j;
  6 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
  7 import org.jetbrains.annotations.NotNull;
  8 
  9 import java.util.concurrent.Callable;
 10 import java.util.concurrent.ExecutorService;
 11 import java.util.concurrent.Executors;
 12 import java.util.concurrent.TimeUnit;
 13 @Slf4j
 14 public class GuavaFutureDemo {
 15     public static void main(String[] args) {
 16         Thread.currentThread().setName("主线程");
 17         ExecutorService executorService = Executors.newFixedThreadPool(10);
 18         DrinkTeaJob drinkTeaJob=new DrinkTeaJob(executorService);
 19         new Thread(drinkTeaJob,"喝茶线程").start();
 20         Callable<Boolean> hotWaterJob = new HotWaterJob();
 21         Callable<Boolean> cleanCapsJob = new CleanCapsJob();
 22         ListeningExecutorService gpool = MoreExecutors.listeningDecorator(executorService);
 23         ListenableFuture<Boolean> hotFuture = gpool.submit(hotWaterJob);
 24         ListenableFuture<Boolean> cleanWaterFuture = gpool.submit(cleanCapsJob);
 25         Futures.addCallback(hotFuture, new FutureCallback<Boolean>() {
 26             @Override
 27             public void onSuccess(@NullableDecl Boolean result) {
 28                 if (result != null) {
 29                     drinkTeaJob.setWaterOk(result);
 30                     drinkTeaJob.setWaterJobDone(true);
 31                 }
 32             }
 33             @Override
 34             public void onFailure(@NotNull Throwable t) {
 35                 drinkTeaJob.setWaterJobDone(true);
 36                 throw new RuntimeException(t.getMessage());
 37             }
 38         },executorService);
 39         Futures.addCallback(cleanWaterFuture, new FutureCallback<Boolean>() {
 40             @Override
 41             public void onSuccess(@NullableDecl Boolean result) {
 42                 if (result != null) {
 43                     drinkTeaJob.setCupsOk(result);
 44                     drinkTeaJob.setCupsJobDone(true);
 45                 }
 46             }
 47             @Override
 48             public void onFailure(@NotNull Throwable t) {
 49                 drinkTeaJob.setCupsJobDone(true);
 50                 throw new RuntimeException(t.getMessage());
 51             }
 52         },executorService);
 53         log.warn("[{}]运行到最后一行代码",Thread.currentThread().getName());
 54     }
 55     static class HotWaterJob implements Callable<Boolean>{
 56         /**
 57          * Computes a result, or throws an exception if unable to do so.
 58          *
 59          * @return computed result
 60          * @throws Exception if unable to compute a result
 61          */
 62         @Override
 63         public Boolean call() throws Exception {
 64             TimeUnit.SECONDS.sleep(2);
 65             if (RandomUtil.randomBoolean()){
 66                 log.info("水已经烧好了...");
 67                 return true;
 68             }
 69             else {
 70                 throw new RuntimeException("火灭了,水烧不开了。。。");
 71             }
 72         }
 73     }
 74     static class CleanCapsJob implements Callable<Boolean>{
 75         /**
 76          * Computes a result, or throws an exception if unable to do so.
 77          *
 78          * @return computed result
 79          * @throws Exception if unable to compute a result
 80          */
 81         @Override
 82         public Boolean call() throws Exception {
 83             TimeUnit.SECONDS.sleep(1);
 84             boolean res;
 85             if (res=RandomUtil.randomBoolean()){
 86                 log.info("茶杯洗好了。。。。");
 87             }
 88             else {
 89                 throw new RuntimeException("茶具摔坏了。。。");
 90             }
 91             return true;
 92         }
 93     }
 94     static class DrinkTeaJob implements Runnable{
 95         private boolean waterOk=false;
 96 
 97         public boolean isWaterJobDone() {
 98             return waterJobDone;
 99         }
100 
101         public void setWaterJobDone(boolean waterJobDone) {
102             this.waterJobDone = waterJobDone;
103         }
104 
105         public boolean isCupsJobDone() {
106             return cupsJobDone;
107         }
108 
109         public void setCupsJobDone(boolean cupsJobDone) {
110             this.cupsJobDone = cupsJobDone;
111         }
112 
113         private boolean waterJobDone=false;
114         private boolean cupsJobDone=false;
115         private boolean cupsOk=false;
116         private final ExecutorService executorService;
117         DrinkTeaJob(ExecutorService executorService){
118             this.executorService=executorService;
119         }
120         public void setWaterOk(boolean waterOk) {
121             this.waterOk = waterOk;
122         }
123 
124         public void setCupsOk(boolean cupsOk) {
125             this.cupsOk = cupsOk;
126         }
127 
128         private int gap=0;
129         /**
130          * When an object implementing interface <code>Runnable</code> is used
131          * to create a thread, starting the thread causes the object's
132          * <code>run</code> method to be called in that separately executing
133          * thread.
134          * <p>
135          * The general contract of the method <code>run</code> is that it may
136          * take any action whatsoever.
137          *
138          * @see Thread#run()
139          */
140         @Override
141         public void run() {
142             while (!Thread.currentThread().isInterrupted())
143             {
144                 log.info("正在学习编程。。。");
145                 try{
146                     TimeUnit.MILLISECONDS.sleep(this.gap);
147                     if (waterJobDone&&cupsJobDone)
148                     {
149                         this.drinkTea();
150                     }
151                 } catch (InterruptedException interruptedException) {
152                     log.error("喝茶线程被中断了",interruptedException);
153                     break;
154                 }
155                 this.gap+=500;
156             }
157             log.info("喝茶线程退出!!");
158             this.executorService.shutdown();
159         }
160 
161         private void drinkTea() throws InterruptedException {
162             if (this.cupsOk&&this.waterOk)
163             {
164                 log.info("泡茶,喝茶,苏福~~~");
165             }else {
166                 log.warn("茶喝不成了,哭。。。。");
167             }
168             TimeUnit.SECONDS.sleep(1);
169             Thread.currentThread().interrupt();
170         }
171     }
172 }

程序运行结果1:

 

程序运行结果2:

 

 

 


posted @ 2020-10-16 16:46  码农小正  阅读(641)  评论(0编辑  收藏  举报