• 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:

    
    
  • 相关阅读:
    Open live Writer
    python两则99乘法表
    更改jupyter-notebook启动时的默认目录
    在内容中插入代码,返回进行编辑时,有无法跳出代码区的情况
    关于jupyter notebook密码设置
    nginx+zuul
    spring-cloud 服务优雅下线
    java.util.ConcurrentModificationException异常排查
    使用bitset实现毫秒级查询(二)
    使用bitset实现毫秒级查询
  • 原文地址:https://www.cnblogs.com/aishangtaxuefeihong/p/13827325.html
Copyright © 2020-2023  润新知