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

    事件介绍 事件的处理机制非常的复杂,属于PyQt底层的事,不必我们关心,学会使用就行.如果说事件是用来创建窗口,那么信号与槽就是用来对这个控件进行处理.事件属于低级的处理方式,信号与槽是高级的处理方式 ...

  2. 设计模式:visitor模式

    核心:将数据结构和数据的处理分开 注意:注意函数的参数传递和调用关系 例子: class Element; class Visitor { public: virtual void Visit(Ele ...

  3. vue使用elementUI form表单label样式修改

    更多关于修改ElementUI样式的方法,可以参考这篇文章 1.删除style标签中的 scoped 属性 <style lang="lang" scoped> ... ...

  4. vue组件库用markdown生成文档

    前言: 开发vue组件库需要提供组件的使用文档,最好是有渲染到浏览器的demo实例,既能操作又能查看源代码.markdown作为常用的文档编写载体,如果能在里面直接写vue组件,同时编写使用说明就再好 ...

  5. java基础(一)注释

    注释的三方方式: 1.多行注释 /* 多行注释01 多行注释02 多行注释03 */

  6. C# File.Exists 判断系统文件,警惕32位和64位的差异

    今天在调试一个Winform程序,使用File.Exists 判断一个已经存在的驱动文件,程序一直返回false.因为驱动文件属于系统目录,心想难道是权限不够导致的?然后用管理员身份运行软件,依然返回 ...

  7. python---filecmp 实现文件,目录,遍历子目录的差异对比功能。

    python---filecmp ilecmp可以实现文件,目录,遍历子目录的差异对比功能. 自带filecmp模块,无需安装. 常用方法说明 filecmp提供3个操作方法,cmp(单文件对比),c ...

  8. C#怎么统计网站当前在线人数

    1.问题背景 c#网站怎么合理的统计在线人数?我想通过全局变量来统计软件的使用情况,当启动软件时向服务器的用户表写开始使用时间,正常退出时写一个结束使用时间,来统计用户的在线使用情况. 但是有一个问题 ...

  9. PHP array_fill_keys() 函数

    ------------恢复内容开始------------ 实例 用给定的指定键名的键值填充数组: <?php$keys=array("a","b",& ...

  10. PHP array_replace() 函数

    实例 使用第二个数组($a2)的值替换第一个数组($a1)的值: <?php$a1=array("red","green");$a2=array(&quo ...