Java多线程③——Guava并发

   //测试Guave版本,测试是最高版本28.1
   <!-- guava 最新版本28.1-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>24.1-jre</version>
<!--            <version>26.0-jre</version>-->
        </dependency>

ListenableFuture简单应用

Guava的ListenableFuture是对多线程使用的一个很好的补充,通过ListenableFuture的addCallback我们可以很好的完成调用成功(onSuccess)或者失败(onFailure)以后的逻辑处理,使用方法如下:

@Slf4j
public class ListenableFutureDemo implements Callable<String>{

    String info;

    public ListenableFutureDemo(String info) {
        this.info = info;
    }

    public static void main(String[] args) {
        log.info("线程{}, 主线程开始---" , Thread.currentThread().getName());
        ExecutorService pool = Executors.newFixedThreadPool(10);
        //将java的包装成Listenable的线程池  Guava提供的返回值是ListenableFuture的线程池
        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(pool);
        ListenableFuture<String> future1 = executorService.submit(new ListenableFutureDemo("昨夜西风凋碧树"));
        ListenableFuture<String> future2 = executorService.submit(new ListenableFutureDemo("独上高楼"));
        //ListenableFuture可以设置callBack  addCallback在addListener基础上封装;
        //在线程执行成和执行失败的策略;设置线程池异步执行callback、不然就是同步执行
        Futures.addCallback(future1, new CallBackDemo(), MoreExecutors.directExecutor());
        Futures.addCallback(future2, new CallBackDemo(), pool);
        log.info("主线程结束");
    }

    @Override
    public String call() throws Exception {
        log.info("线程{}, 工作线程执行完成:{}" , Thread.currentThread().getName(), info);
        if(true){
            throw new RuntimeException("我执行失败了");
        }
        return info;
    }
}

@Slf4j
class CallBackDemo implements FutureCallback<String> {

    @Override
    public void onSuccess(@NullableDecl String o) {
        log.info("线程{}, callback成功响应开始:{}" , Thread.currentThread().getName(), o);
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("线程{}, callback成功响应结束:{}" , Thread.currentThread().getName(), o);
    }

    @Override
    public void onFailure(Throwable throwable) {
        log.info("线程{}, callback失败响应:{}" , Thread.currentThread().getName());
    }
}

根据上面代码我们可以看到,关键类如下:

MoreExecutors:该类是final类型的工具类,提供了很多静态方法。比如ListeningDecorator方法将java线程池装饰为ListeningExecutorService,使用此实例submit方法即可初始化ListenableFuture对象。

ListeningExecutorService:该类是对ExecutorService的扩展,重新ExecutorService类中的submit方法,返回ListenableFuture对象。

ListenableFuture:该接口扩展了Future接口,增加了addListener方法,该方法在给定的executor上注册一个监听器,当计算完成时会马上调用该监听器。不能够确保监听器执行的顺序,但可以在计算完成时确保马上被调用。addListener和addCallback本质是一样的,addCallback是在addListener的基础上做了封装。

FutureCallback:该接口提供了OnSuccess和OnFailure方法。获取异步计算的结果并回调。

Futures:该类提供了很多实用的静态方法以供实用。设置同步执行回调还是异步执行回调

ListenableFutureTask:该类扩展了FutureTask类并实现了ListenableFuture接口,增加了addListener方法。

///将一个 ExecutorService 转换为 ListeningExecutorService,MoreExecutors装饰
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
//Guava提供两个callBack用于ListenableFuture回调,高版本已经去掉第二个方法
Futures.addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback, Executor executor);
Futures.addCallback(ListenableFuture<V> future, FutureCallback<? super V> callback);
// 但是你可以继续设置当前线程
MoreExecutors.directExecutor()

SettableFuture简单介绍

@Slf4j
public class SettableFutureDemo implements Callable<String> {

    static ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));

    public static void main(String[] args) {
        testSettableFuture(); //规定时间拿到结果;适合需要在规定时间拿结果的应用;指定时间拿不到结果抛出异常
    }

    //如果执行任务线程超时,并不会中断执行;set完成后即可拿到响应结果
    public static void testSettableFuture(){
        SettableFuture<String> settableFuture = SettableFuture.create();
        ListenableFuture<String> future = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                TimeUnit.SECONDS.sleep(5);
                settableFuture.set("得到世界");
                log.info("会继续走下去么??");
                return "测试";
            }
        });
        try {
            Futures.addCallback(future,  new FutureCallback<String>() {
                @Override
                public void onSuccess(@Nullable String result) {
                    log.info("执行成功响应:{}", result);
                }

                @Override
                public void onFailure(Throwable th) {
                    log.error("执行失败", th);
                }
            } ,executorService);
            log.info("settableFuture 规定时间检测:" + settableFuture.get(2, TimeUnit.SECONDS));
            // set完成后即可拿到响应结果
            //log.info("settableFuture 规定时间检测:" + settableFuture.get(10, TimeUnit.SECONDS));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String call() throws Exception {
        TimeUnit.SECONDS.sleep(2);
        return "测试";
    }
}

SettableFuture: 适合规定时间拿到SettableFuture set值;Set结果后即可返回、响应

适合在规定时间拿到结果的应用;规定时间没拿到就报错;

但是注意当前任务执行线程会继续执行,OnSuccess也会成功执行

Futures简介

@Slf4j
public class FuturesMethodDemo {
    static ExecutorService pool = Executors.newFixedThreadPool(5);//定义线程数

    /**
     * Futures相关
     **/
    //对多个结果进行处理
    //allAsList:对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。注:当其中一个Future失败或者取消的时候,将会进入失败或者取消。
    //successfulAsList:和allAsList相似,唯一差别是对于失败或取消的Future返回值用null代替。不会进入失败或者取消流程。

    //Futures.transform:对于ListenableFuture的返回值进行转换。
    //immediateFuture/immediateCancelledFuture: 立即返回一个待返回值的ListenableFuture。
    //将ListenableFuture 转换成CheckedFuture。CheckedFuture 是一个ListenableFuture ,其中包含了多个版本的get 方法,方法声明抛出检查异常.这样使得创建一个在执行逻辑中可以抛出异常的Future更加容易
    //JdkFutureAdapters.listenInPoolThread(future): guava同时提供了将JDK Future转换为ListenableFuture的接口函数。

    // ThreadFactoryBuilder 方便的threadFactory--- 可以了解下threadFactory
    //ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("测试").build();
    public static void main(String[] args) {
        List<String> list = createTickets();//获取车票
        List<ListenableFuture<Integer>> futures = Lists.newArrayList();

        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(pool);
        for (int i = 0; i < list.size(); i++) {
            futures.add(executorService.submit(new Task(list.get(i))));
        }
        //testAsList(futures);
        transforResult(testAsList(futures));
        pool.shutdown();
    }

    public static ListenableFuture<List<Integer>> testAsList(List<ListenableFuture<Integer>> futures) {
        /**   successfulAsList和allAsList  **/
        //allAsList:对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。注:当其中一个Future失败或者取消的时候,将会进入失败或者取消
         //ListenableFuture<List<Integer>> resultsFuture = Futures.allAsList(futures);
        //successfulAsList:和allAsList相似,唯一差别是对于失败或取消的Future返回值用null代替。不会进入失败或者取消流程。
         ListenableFuture<List<Integer>> resultsFuture = Futures.successfulAsList(futures);

        try {
            //所有都执行完毕
            List<Integer> integers = resultsFuture.get();
            log.info("结果:" + integers.stream().map(i -> i + "").collect(Collectors.joining(",")));
        } catch (Exception e) {
            log.error("出错了", e);
        } finally {
            log.info("操作完毕");
        }
        return resultsFuture;
    }

    //将所有的结果,好分割,输出字符串  立即返回一个待返回值的ListenableFuture。
    public static void transforResult(ListenableFuture<List<Integer>> resultsFuture) {
        /** AsyncFunction和  immediateFuture **/
        ListenableFuture<String> transformAsync = Futures.transformAsync(resultsFuture, new AsyncFunction<List<Integer>, String>() {
            @Override
            public ListenableFuture<String> apply(@NullableDecl List<Integer> result) throws Exception {
                return Futures.immediateFuture(result.stream().map(i -> i + "").collect(Collectors.joining(",")));
            }
        }, pool);

        try {
            log.info("转换后的结果{}", transformAsync.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static List<String> createTickets() {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add("车票" + i);
        }
        return list;
    }

}

@Slf4j
class Task implements Callable<Integer> {
    private String ticket;

    public Task(String ticket) {
        this.ticket = ticket;
    }

    @Override
    public Integer call() throws Exception {
        if (ticket.equals("车票5")) {
            throw new Exception();
        }
        log.info("已卖" + ticket);
        return 1;
    }
}

Futures.allAsList():将ListenableFuture集合结果合并处理;

如果其中一个futures失败报错,执行get获取结果是会报错

Futures.successfulAsList:同allAsList类似,但是会将执行失败的future结果替换为null;

执行get获取结果时不会失败

 

Futures.transform/:对于ListenableFuture的返回值进行转换。

transformAsync 同上

immediateFuture/immediateCancelledFuture: 立即返回一个待返回值的ListenableFuture

 

 

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值