从Java Future到Guava ListenableFuture实现异步调用
原文地址: http://blog.csdn.net/pistolove/article/details/51232004
Java Future
通过Executors可以创建不同类似的线程池,常见的大概有下表几种类型,还有些可能为被列出。在实际应用中,个人感觉主要使用newCachedThreadPook和newFixedThreadPool来创建线程池。
Executors创建线程池源码
//调用newCachedThreadPool方法,可以创建一个缓冲型线程池,而在改方法中通过传参创建一个ThreadPoolExecutor,也许你会很奇怪明明返回的是一个ExecutorService,怎么会创建了一个ThreadPoolExecutor呢?
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L,
TimeUnit.SECONDS, new SynchronousQueue<Runnable());
}
// ThreadPoolExecutor继承了抽象的service类AbstractExecutorService
public class ThreadPoolExecutor extends AbstractExecutorService {}
//AbstractExecutorService实现了ExecutorService接口
public abstract class AbstractExecutorService implements ExecutorService {}
//所以ExecutorService其实是ThreadPoolExecutor的基类,这也就解释清楚了
ExecutorService(线程池)
ExecutorService是一个接口,它继承了Executor,在原有execute方法的基础上新增了submit方法,传入一个任务,该方法能够返回一个Future对象,可以获取异步计算结果。
//ExecutorService继承了Executor,并扩展了新方法。
public interface ExecutorService extends Executor { }
//Executor中的方法
void execute(Runnable command);
//增加了submit方法,该方法传任务来获取Future对象,而Future对象中可以获取任务的执行结果
<T> Future<T> submit(Callable<T> task);
Future<?> submit(Runnable task);
Future(获取异步计算结果)
Future接口中有下表所示方法,可以获取当前正在执行的任务相关信息。
FutureTask
Executor框架利用FutureTask来完成异步任务,并可以用来进行任何潜在的耗时计算,一般FutureTask多用于耗时的计算,主线程可以在完成自己任务后,再去获取结果。
FutureTask包装了Callable和Runnable接口对象,提供了对Future接口的基本实现,开始、取消计算、查询结果是否完成、获取计算结果。仅当计算完成时才能检索结果,当计算没有完成时,该方法会一直阻塞直到任务转入完成状态。一旦完成计算,不能够重新开始或取消计算。通过Excutor(线程池)来执行,也可传递给Thread对象执行。如果在主线程中需要执行比较耗时的操作时,但又不想阻塞主线程时,可以把这些作业交给Future对象在后台完成,当主线程将来需要时,就可以通过Future对象获得后台作业的计算结果或者执行状态。
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestFuture {
// 创建线程池
final static ExecutorService service = Executors.newCachedThreadPool();
public static void main(String[] args) throws InterruptedException, ExecutionException {
Long t1 = System.currentTimeMillis();
// 任务1
Future<Boolean> booleanTask = service.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return true;
}
});
while (true) {
if (booleanTask.isDone() && !booleanTask.isCancelled()) {
//模拟耗时
Thread.sleep(500);
Boolean result = booleanTask.get();
System.err.println("BooleanTask: " + result);
break;
}
}
// 任务2
Future<String> stringTask = service.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "Hello World";
}
});
while (true) {
if (stringTask.isDone() && !stringTask.isCancelled()) {
String result = stringTask.get();
System.err.println("StringTask: " + result);
break;
}
}
// 任务3
Future<Integer> integerTask = service.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return new Random().nextInt(100);
}
});
while (true) {
if (integerTask.isDone() && !integerTask.isCancelled()) {
Integer result = integerTask.get();
System.err.println("IntegerTask: " + result);
break;
}
}
// 执行时间
System.err.println("time: " + (System.currentTimeMillis() - t1));
}
}
Guava Future
ListenableFuture是可以监听的Future,它是对Java原始Future的扩展增强。Future表示一个异步计算任务,当任务完成时可以得到计算结果。如果希望计算完成时马上就拿到结果展示给用户或者做另外的计算,就必须使用另一个线程不断的查询计算状态。这样做会使得代码复杂,且效率低下。如果使用ListenableFuture,Guava会帮助检测Future是否完成了,如果完成就自动调用回调函数,这样可以减少并发编程的复杂度。
常用API
1. MoreExecutors
该类是final类型的工具类,提供了很多静态方法。比如ListeningDecorator方法初始化ListeningExecutorService方法,使用此实例submit方法即可初始化ListenableFuture对象。
2. ListeningExecutorService
该类是对ExecutorService的扩展,重新ExecutorService类中的submit方法,返回ListenableFuture对象。
3. ListenableFuture
该接口扩展了Future接口,增加了addListener方法,该方法在给定的executor上注册一个监听器,当计算完成时会马上调用该监听器。不能够确保监听器执行的顺序,但可以在计算完成时确保马上被调用。
4. FutureCallback
该接口提供了OnSuccess和OnFailure方法。获取异步计算的结果并回调。
5. Futures
该类提供了很多实用的静态方法以供实用。
6. ListenableFutureTask
该类扩展了FutureTask类并实现了ListenableFuture接口,增加了addListener方法。
7.
public class TestListenableFuture2 {
// 创建线程池
final static ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
public static void main(String[] args) throws Exception {
Long t1 = System.currentTimeMillis();
// 任务1
ListenableFuture<Boolean> booleanTask = service.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
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 {
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 {
return new Random().nextInt(100);
}
});
Futures.addCallback(integerTask, new FutureCallback<Integer>() {
@Override
public void onSuccess(Integer result) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("IntegerTask: " + result);
}
@Override
public void onFailure(Throwable t) {
}
});
// 执行时间
System.err.println("time: " + (System.currentTimeMillis() - t1));
}
}
从Java Future到Guava ListenableFuture实现异步调用的更多相关文章
- 从Java future 到 Guava ListenableFuture实现异步调用
从Java future 到 Guava ListenableFuture实现异步调用 置顶 2016年04月24日 09:11:14 皮斯特劳沃 阅读数:17570 标签: java异步调用线程非阻 ...
- java future模式 所线程实现异步调用(转载
java future模式 所线程实现异步调用(转载) 在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决.Future顾名思意,有点像期货市场 ...
- Future 异步回调 大起底之 Java Future 与 Guava Future
目录 写在前面 1. Future模式异步回调大起底 1.1. 从泡茶的案例说起 1.2. 何为异步回调 1.2.1. 同步.异步.阻塞.非阻塞 1.2.2. 阻塞模式的泡茶案例图解 1.2.3. 回 ...
- SpringBoot系列——@Async优雅的异步调用
前言 众所周知,java的代码是同步顺序执行,当我们需要执行异步操作时我们需要创建一个新线程去执行,以往我们是这样操作的: /** * 任务类 */ class Task implements Run ...
- java Future && Guava Future
### java future Runnable的任务是没有返回值,也不能抛出异常的java.util.concurrent.Callable接口,可以返回一个对象或者抛出异常 使用jdk的这种方式提 ...
- 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】
四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...
- Transform java future into completable future 【将 future 转成 completable future】
Future is introduced in JDK 1.5 by Doug Lea to represent "the result of an asynchronous computa ...
- 浅谈Java Future接口
Java项目编程中,为了充分利用计算机CPU资源,一般开启多个线程来执行异步任务.但不管是继承Thread类还是实现Runnable接口,都无法获取任务执行的结果.JDK 5中引入了Callable和 ...
- java Future 模式
考慮這樣一個情況,使用者可能快速翻頁瀏覽文件中,而圖片檔案很大,如此在瀏覽到有圖片的頁數時,就會導致圖片的載入,因而造成使用者瀏覽文件時會有停頓 的現象,所以我們希望在文件開啟之後,仍有一個背景作業持 ...
随机推荐
- 洛谷3690:【模板】Link Cut Tree——题解
https://www.luogu.org/problemnew/show/P3690 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- 【极值问题】【CF1063B】 Labyrinth
传送门 Description 给你一个\(n~\times~m\)的矩阵,一开始你在第\(r\)行第\(c\)列.你的上下移动不受限制,向左最多移动\(x\)次,向右最多移动\(y\)次.求你最多能 ...
- 关于JavaScript的沙箱模式
从语言学的角度上来说,允许代码无节制地使用全局变量,是最错误的选择之一.而更可怕的,就是一个变量"可能"成为全局的(在未知的时间与地点).但是这两项,却伴随JavaScript这门 ...
- Codeforces Round #345 (Div. 2) A
A. Joysticks time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- Codeforces Round #547 (Div. 3) 题解
Codeforces Round #547 (Div. 3) 题目链接:https://codeforces.com/contest/1141 A,B咕咕了... C. Polycarp Restor ...
- bzoj 4831 [Lydsy1704月赛]序列操作 dp
[Lydsy1704月赛]序列操作 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 203 Solved: 69[Submit][Status][Dis ...
- 查看自己电脑外网IP
连着wifi,在CMD窗口中显示的无线局域网适配器IP很有可能是内网IP.此时可以通过下面方法查看自己的电脑外网IP. 1.前提条件可以上外网: 2.上外网百度,输入IP,进行搜索. 3.查看结果即可 ...
- echarts 使用demo
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>ECharts</t ...
- SourceTree for mac 注册过程(v2.7.6a)
背景 为啥要自己注册呢,往上一堆一堆的老版本许可证偏不用,就愿意定制自己的账号style. 搞了半天,还是觉得pycharm自带的git工具就挺好用了,闲的没事记录一下. 要点 百度搜索的地址可以进入 ...
- PHP系统编程--01.多进程与多线程
PHP中提供了一个扩展pcntl,可以利用操作系统的fork调用来实现多进程.fork调用后执行的代码将是并行的. PHP官方没有提供多线程的扩展,pecl中有一个pthreads扩展提供了多线程的特 ...