随着软件开发的不断进步,在实际的开发应用中,可能一次请求需要查询若干次数据库或者调用若干次第三方,按照传统的串行执行的话,会大大增加响应时间,无法满足业务需求,更无法满足用户迫切需要响应迅速的愿望。对此,我们需要针对网络请求或内部调用中包含的“多任务”进行异步处理,并行去执行这些“任务”,这样就就会大大减小响应时间。本文是基于guava中的ListenableFuture来实现的。

测试代码:

 package com.study1;

 import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.LockSupport; import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
/**
* GUAVA ListenableFuture
* @author gaojy
*
*/
public class TestListenableFuture {
//定义一个线程池,用于处理所有任务
final static ListeningExecutorService service
= MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); public static void main(String[] args){
Long t1 = System.currentTimeMillis();
// 任务1
ListenableFuture<Boolean> booleanTask = service.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
Thread.sleep(10000);
return true;
}
}); /**
*
*/
Futures.addCallback(booleanTask, new FutureCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
System.err.println("BooleanTask: " + result);
} @Override
public void onFailure(Throwable t) {
}
}); // 任务2
ListenableFuture<String> stringTask = service.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(10000);
return "Hello World";
}
}); Futures.addCallback(stringTask, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.err.println("StringTask: " + result);
} @Override
public void onFailure(Throwable t) {
}
}); // 任务3
ListenableFuture<Integer> integerTask = service.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(10000);
return new Random().nextInt(100);
}
}); Futures.addCallback(integerTask, new FutureCallback<Integer>() {
@Override
public void onSuccess(Integer result) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("IntegerTask: " + result);
} @Override
public void onFailure(Throwable t) {
}
}); // 执行时间
System.err.println("time: " + (System.currentTimeMillis() - t1)); }
}

测试结果:

源码分析:

在26行中ListeningExecutorService的submit()方法:

 public ListenableFuture submit(Runnable task, Object result)
{
// 初始化了ListenableFutureTask对象
ListenableFutureTask ftask = ListenableFutureTask.create(task, result);
//执行task,实际上调用了Callable对象的call()方法
execute(ftask);
return ftask;
}

再来查看一下Futures.addCallback的方法:

 public static void addCallback(ListenableFuture future, FutureCallback callback, Executor executor)
{
//对回调task进行检查
Preconditions.checkNotNull(callback);
//创建一个新的Runnable对象,并放到一个指定的线程中,执行。
//这个Runnable对象主要任务就是获得future的结果,并根据结果调用回调函数的相应方法
Runnable callbackListener = new Runnable(future, callback) { public void run()
{
Object value;
try
{
//获取future执行结果,内部调用future.get(),产生堵塞,而不影响main主线程的执行,当获取到value时,就调用callback的onSuccess()方法
value = Uninterruptibles.getUninterruptibly(future);
}
catch(ExecutionException e)
{
callback.onFailure(e.getCause());
return;
}
catch(RuntimeException e)
{
callback.onFailure(e);
return;
}
catch(Error e)
{
callback.onFailure(e);
return;
}
callback.onSuccess(value);
} final ListenableFuture val$future;
final FutureCallback val$callback; {
future = listenablefuture;
callback = futurecallback;
super();
}
}
;
future.addListener(callbackListener, executor);
}

GUAVA-ListenableFuture实现回调的更多相关文章

  1. 从Java future 到 Guava ListenableFuture实现异步调用

    从Java future 到 Guava ListenableFuture实现异步调用 置顶 2016年04月24日 09:11:14 皮斯特劳沃 阅读数:17570 标签: java异步调用线程非阻 ...

  2. 从Java Future到Guava ListenableFuture实现异步调用

    原文地址: http://blog.csdn.net/pistolove/article/details/51232004 Java Future     通过Executors可以创建不同类似的线程 ...

  3. google Guava包的ListenableFuture解析

     一. ListenableFuture是用来增强Future的功能的. 我们知道Future表示一个异步计算任务,当任务完成时可以得到计算结果.如果我们希望一旦计算完成就拿到结果展示给用户或者做另外 ...

  4. Future 异步回调 大起底之 Java Future 与 Guava Future

    目录 写在前面 1. Future模式异步回调大起底 1.1. 从泡茶的案例说起 1.2. 何为异步回调 1.2.1. 同步.异步.阻塞.非阻塞 1.2.2. 阻塞模式的泡茶案例图解 1.2.3. 回 ...

  5. Guava - 并行编程Futures

    Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展. 继承至Future的ListenableFuture,允许我 ...

  6. 初探Google Guava

    Guava地址:https://github.com/google/guava 第一次接触我是在16年春github上,当时在找单机查缓存方法,google guava当初取名是因为JAVA的类库不好 ...

  7. Guava future

    减少主函数的等待时间,使得多任务能够异步非阻塞执行 ListenableFuture是可以监听的Future,它是对java原生Future的扩展增强.Future表示一个异步计算任务,当任务完成时可 ...

  8. 多线程学习-ListenableFuture使用介绍以及示例

    Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展.ListenableFuture顾名思义就是可以监听的Futu ...

  9. Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)

    一.回调函数 为什么首先会讲回调函数呢?因为这个是理解监听器.观察者模式的关键. 什么是回调函数 所谓的回调,用于回调的函数. 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数. ...

  10. Guava cacha 机制及源码分析

    1.ehcahce 什么时候用比较好:2.问题:当有个消息的key不在guava里面的话,如果大量的消息过来,会同时请求数据库吗?还是只有一个请求数据库,其他的等待第一个把数据从DB加载到Guava中 ...

随机推荐

  1. Java历史[史上最详细的阐述了Java发展的历史过程]

    Java历史 学习Java语言之前,我觉得大家应该是从头开始,对吧?不管你之前是学过还是没学过,都和学习某一个知识一样,从头开始去了解它,然后到这个深入的掌握,到最后你可能理解并且灵活的运用.所以它肯 ...

  2. “Python的单例模式有四种写法,你知道么?”——孔乙己

    什么是单例模式 单例模式(Singleton Pattern)是最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式涉及到一个单一的类,该类负责创建自己的 ...

  3. 请解释ASP.NET中的web页面与其隐藏类之间的关系

    其实页面与其隐藏类之间就是一个部分类的关系,你在页面上放一个一个的控件就是在这个类中定义一个一个的属性, 因为是同一个类的部分类的关系,所以隐藏类可以访问到页面上控件,这样做是为了把展现与处理逻辑分开 ...

  4. JDBC 连接 MySQL 8.0.15+ 常见错误记录

    课后复习 1. No suitable driver found for mysql:jdbc://localhost:3306/test 错误原因: mysql:jdbc://localhost:3 ...

  5. php必须掌握的常用函数

    数学函数 数组函数 字符串函数

  6. python-闭包和装饰器-01-闭包(closure)

    闭包(closure) 闭包就是在一个函数定义的内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包,如: def line(a, b): def cal( ...

  7. 图片懒加载、ajax异步调用数据、lazyload插件的使用

    关于这个效果还是很简单的,样式部分我就不多说了,我就简单的写了一下布局, 这是css样式 我们先说一下实现的原理. 我们都知道在于图片的引入,我们都是用src来引入图片地址.从而实现图片的显示.那我们 ...

  8. umount 报错

    在umount时报错: [root@node1 ~]# umount /usbumount: /usb: target is busy. (In some cases useful info abou ...

  9. smartSVN9.2.2 for mac 安装与破解

    原文链接:https://www.jianshu.com/p/bb87154e0459 近段时间使用svn进行项目管理,开始使用的是cornerstone,但是用过程中出现一个操作Bug,一.在xco ...

  10. Python File flush() 方法

    概述 flush() 方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入.高佣联盟 www.cgewang.com 一般情况下,文件关闭后会自动刷 ...