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

一、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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,560评论 18 399
  • //Clojure入门教程: Clojure – Functional Programming for the J...
    葡萄喃喃呓语阅读 3,616评论 0 7
  • 曾有人说过,爱情没有天荒地老也没有执手一生,有的不过是救赎,有人救赎他人的时间较长,有人救赎他人的时间短如一瞬。 ...
    槐绫阅读 420评论 0 1
  • 一个人走在这星空之上 探索星球留下的远古遗迹 我的眼眸如星空般深邃 除了脚印什么都没有 我的身边多了一个人 那是我...
    夏江南爱上夏雨荷阅读 547评论 0 2