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:

 

 

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM