美文网首页JavaWeb 知识点Java学习笔记javase
总结一下guava常用并发库的用法

总结一下guava常用并发库的用法

作者: jerrik | 来源:发表于2017-09-29 12:57 被阅读2803次
    一、ThreadFactoryBuilder

    ThreadFactoryBuilder主要用于线程池技术中。当我们需要给新创建的线程取名字、或者设置为守护线程、错误处理器等操作时,线程工厂的好处就提现出来了。

    1. 不用ThreadFactoryBuilder的时候 我们这么写代码。我们每次要新建一个类来实现ThreadFactory,有点繁琐。
    image.png
    1. 用了ThreadFactoryBuilder之后,好处不言而喻。ThreadFactoryBuilder是一个Builder设计模式的应用,可以设置守护进程、错误处理器、线程名字。
    image.png
    二、SettableFuture

    settableFuture我们可以认为是一种异步转同步的工具。我们平常只听说过同步转异步,这次竟然是异步转同步,是不是觉得有点奇怪。先看一下实例:

    我们先使用create()创建一个SettableFuture的实例,然后等线程获取结果后手动将返回值放入到settableFuture中,类似于一个ThreadLocal.,一切看起来都很自然。但是作用在哪?个人认为就是get()方法,我们可以设置超时获取的时间,如果在指定时间内获取不到,则抛出异常。


    image.png
    应用场景:

    我们在做网络通信时,假设一般请求-响应都是在3秒以内拿到结果.但有的时候遇到网络动荡、硬件性能问题时会导致超时,5秒,10秒甚至更多。但是我们希望超过5秒的请求我们就认为失败,这个时候SettableFuture就可以出场了,代码优雅,又能解决实际问题。

    remoteFuture.get(5,TimeUnit.SECONDS);
    
    三、ListenableFuture

    ListenableFuture是基于装饰器模式实现的:

        ListeningExecutorService listeningExecutor = MoreExecutors.listeningDecorator(executor);
        final ListenableFuture<String> future = listeningExecutor.submit(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    TimeUnit.SECONDS.sleep(2);
                    return "hello_world";
                }
            });
    

    我们可以对ExecutorService做一层包装,返回一个ListenableFuture实例,而ListenableFuture又是集成自Future,扩展了一个addListener监听方法,当任务执行完成,会主动回调该方法。主要也是弥补了JDK自带Future的不足,像Netty也优雅的实现了异步回调机制,不需要手动通过Future.get()来获取结果。

            future.addListener(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("收到通知..." + future.get());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            }, listeningExecutor);
    
    四、Futures.addCallback

    也是基于异步回调的机制,个人觉得更加雅观。

            Futures.addCallback(future, new FutureCallback<String>() {
    
                @Override
                public void onSuccess(String result) {
                }
    
                @Override
                public void onFailure(Throwable t) {
                    System.out.println("futureException: ");
                    t.printStackTrace();
                }
            });
    
    五、AsyncFunction

    我们调用ListenableFuture.get方法取回AsyncFunction接口处理后的结果。当我们想要异步地执行转换逻辑,而不是阻塞的调用(虽然任务还没有完成的时候调用Future.get方法会阻塞)的时候,可以使用AsyncFunction接口。但是AsyncFunction接口并不会异步的执行转换逻辑;而只是返回一个Future实例。 看看下面代码例子:

    public class AsyncFuntionSample implements AsyncFunction<Long,String> {
        private ConcurrentMap<Long,String> map = Maps.newConcurrentMap();
        private ListeningExecutorService listeningExecutorService;
    
        @Override
        public ListenableFuture<String> apply(final Long input) throws Exception {
        if(map.containsKey(input)) {
            SettableFuture<String> listenableFuture = SettableFuture.create();
            listenableFuture.set(map.get(input));
            return listenableFuture;
        }else{
            return listeningExecutorService.submit(new Callable<String>(){
            @Override
            public String call() throws Exception {
                String retrieved = service.get(input);
                map.putIfAbsent (input,retrieved);
                return retrieved;
            }
        });
        }
    }
    

    我们这个类实现AsyncFunction接口,并且包含一个ConcurrentHashMap实例。当我们调用apply方法时,我们会首先查看下map中有没有这个值,输入对象作为key。如果我们在map中找到值,我们使用SettableFuture类构造出Future对象,并且设置为从map中取出的对象。否则,我们返回提交Callable给ExecutorService放回的Future对象。同样也会放置返回的值到map中去。

    六、补充一下

    Futures中还有几个immediate开头的方法:

    //immediateFuture 表示该方法立即返回
    ListenableFuture<String> future = Futures.immediateFuture("immediateFuture");
    
    //实现和immediateFuture差不多,提供了两个checkedGet()方法
    future = Futures.immediateCheckedFuture("immediateCheckedFuture");
            
    //构造一个cancel的future,当调用get()方法时  立即抛出异常
    future = Futures.immediateCancelledFuture();
    
    //调用get()方法和checkedGet()抛出异常        
    future =Futures.immediateFailedCheckedFuture(newNullPointerException("immediateFailedCheckedFuture"));
            
    //当调用get()方法时,抛出异常
    future = Futures.immediateFailedFuture(new NullPointerException("immediateFailedFuture"));
    

    这些方法一般结合着Futures的transform使用:

    ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
            ListenableFuture<Integer> futures = executor.submit(new Callable<Integer>() {
                public Integer call() throws Exception {
                    Thread.sleep(2000);
                    System.out.println("future task done......");
                    return 1;
                }
            });
    //因为futures.get()返回的是Integer,如果想在get()方法返回之后,利用其返回值做一些其他操作.就可以使用
    transform()方法,手动转换为对其类型结果的获取:
            ListenableFuture<Boolean> transform = Futures.transformAsync(futures, new AsyncFunction<Integer, Boolean>() {
                public ListenableFuture<Boolean> apply(Integer integer) throws Exception {
                    return integer > 0 ? Futures.immediateFuture(Boolean.TRUE) : Futures.immediateFuture(Boolean.FALSE);
                }
            });
    

    使用JdkFutureAdapters来完成JDK Future到ListenableFuture的转换:

      ListenableFuture<Boolean> listenFuture = JdkFutureAdapters.listenInPoolThread(transformFuture);
    

    更多详情可以参考: https://stonelion.gitbooks.io/guava_ch/content/index.html

    相关文章

      网友评论

        本文标题:总结一下guava常用并发库的用法

        本文链接:https://www.haomeiwen.com/subject/hpwbextx.html