GUAVA-ListenableFuture实现回调
随着软件开发的不断进步,在实际的开发应用中,可能一次请求需要查询若干次数据库或者调用若干次第三方,按照传统的串行执行的话,会大大增加响应时间,无法满足业务需求,更无法满足用户迫切需要响应迅速的愿望。对此,我们需要针对网络请求或内部调用中包含的“多任务”进行异步处理,并行去执行这些“任务”,这样就就会大大减小响应时间。本文是基于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实现回调的更多相关文章
- 从Java future 到 Guava ListenableFuture实现异步调用
从Java future 到 Guava ListenableFuture实现异步调用 置顶 2016年04月24日 09:11:14 皮斯特劳沃 阅读数:17570 标签: java异步调用线程非阻 ...
- 从Java Future到Guava ListenableFuture实现异步调用
原文地址: http://blog.csdn.net/pistolove/article/details/51232004 Java Future 通过Executors可以创建不同类似的线程 ...
- google Guava包的ListenableFuture解析
一. ListenableFuture是用来增强Future的功能的. 我们知道Future表示一个异步计算任务,当任务完成时可以得到计算结果.如果我们希望一旦计算完成就拿到结果展示给用户或者做另外 ...
- Future 异步回调 大起底之 Java Future 与 Guava Future
目录 写在前面 1. Future模式异步回调大起底 1.1. 从泡茶的案例说起 1.2. 何为异步回调 1.2.1. 同步.异步.阻塞.非阻塞 1.2.2. 阻塞模式的泡茶案例图解 1.2.3. 回 ...
- Guava - 并行编程Futures
Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展. 继承至Future的ListenableFuture,允许我 ...
- 初探Google Guava
Guava地址:https://github.com/google/guava 第一次接触我是在16年春github上,当时在找单机查缓存方法,google guava当初取名是因为JAVA的类库不好 ...
- Guava future
减少主函数的等待时间,使得多任务能够异步非阻塞执行 ListenableFuture是可以监听的Future,它是对java原生Future的扩展增强.Future表示一个异步计算任务,当任务完成时可 ...
- 多线程学习-ListenableFuture使用介绍以及示例
Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展.ListenableFuture顾名思义就是可以监听的Futu ...
- Java设计模式补充:回调模式、事件监听器模式、观察者模式(转)
一.回调函数 为什么首先会讲回调函数呢?因为这个是理解监听器.观察者模式的关键. 什么是回调函数 所谓的回调,用于回调的函数. 回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数. ...
- Guava cacha 机制及源码分析
1.ehcahce 什么时候用比较好:2.问题:当有个消息的key不在guava里面的话,如果大量的消息过来,会同时请求数据库吗?还是只有一个请求数据库,其他的等待第一个把数据从DB加载到Guava中 ...
随机推荐
- C++语法小记---重载逗号操作符
重载逗号操作符 逗号操作符算法:从左到右依次计算每一个表达式的值,整个逗号表达式的值等于最右边表达式的值,前面n-1个表达式可以没有返回值 重载逗号操作符: 参数必须有一个class成员 重载函数返回 ...
- vue history路由模式 Nginx 生产实践
nginx(带二级目录的配置) location ~* /A { alias /opt/nginx-1.4.7/html/ued/A; try_files $uri $uri /A/s ...
- 【Nginx】如何使用Nginx搭建流媒体服务器实现直播?看完这篇我会了!!
写在前面 最近几年,直播行业比较火,无论是传统行业的直播,还是购物.游戏.教育,都在涉及直播.作为在互联网行业奋斗了多年的小伙伴,你有没有想过如果使用Nginx搭建一套直播环境,那我们该如何搭建呢?别 ...
- 简单理解:数据库的一致性与四种隔离级别(+MySQL实现)
并行数据库存在着几种常见不一致问题: 1.更新丢失:两个并发的写进程同时修改某内容,一个没修改完提交之后另一个又提交,导致其覆盖了第一个提交的写进程内容. 2.脏读:一个操作读到了另外一个操作没有提交 ...
- Java基础篇(03):流程控制语句,和算法应用
本文源码:GitHub·点这里 || GitEE·点这里 一.分支语句 流程控制语句对任何一门编程语言都是非常重要的,Java中基于流程控制程序执行的不同步骤和代码块. 1.IF条件 IF条件语句会根 ...
- 构建一个基于事件分发驱动的EventLoop线程模型
在之前的文章中我们详细介绍过Netty中的NioEventLoop,NioEventLoop从本质上讲是一个事件循环执行器,每个NioEventLoop都会绑定一个对应的线程通过一个for(;;)循环 ...
- Nginx配置各种响应头防止XSS,点击劫持,frame恶意攻击
为什么要配置HTTP响应头? 不知道各位有没有被各类XSS攻击.点击劫持 (ClickJacking. frame 恶意引用等等方式骚扰过,百度联盟被封就有这些攻击的功劳在里面.为此一直都在搜寻相关防 ...
- phpbasic
<!DOCTYPE html> <html> <body> <?php // 这是 PHP 单行注释 /* 这是 PHP 多行 注释 */ ?> < ...
- let、const、var的区别
1.使用var声明的变量,其作用域为全局或者该语句所在的函数内,且存在变量提升现象. 下面使用node.js演示,也可以插入到html文件中使用以下代码 var a = 10; function te ...
- Python globals和locals函数_reload函数
Python globals和locals函数_reload函数: globals( ): 返回所有能够访问到的全局名字 num = 5 sum = 0 def add(num): func_sum ...