原文地址: 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实现异步调用的更多相关文章

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

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

  2. java future模式 所线程实现异步调用(转载

    java future模式 所线程实现异步调用(转载) 在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决.Future顾名思意,有点像期货市场 ...

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

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

  4. SpringBoot系列——@Async优雅的异步调用

    前言 众所周知,java的代码是同步顺序执行,当我们需要执行异步操作时我们需要创建一个新线程去执行,以往我们是这样操作的: /** * 任务类 */ class Task implements Run ...

  5. java Future && Guava Future

    ### java future Runnable的任务是没有返回值,也不能抛出异常的java.util.concurrent.Callable接口,可以返回一个对象或者抛出异常 使用jdk的这种方式提 ...

  6. 006-优化web请求二-应用缓存、异步调用【Future、ListenableFuture、CompletableFuture】、ETag、WebSocket【SockJS、Stomp】

    四.应用缓存 使用spring应用缓存.使用方式:使用@EnableCache注解激活Spring的缓存功能,需要创建一个CacheManager来处理缓存.如使用一个内存缓存示例 package c ...

  7. 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 ...

  8. 浅谈Java Future接口

    Java项目编程中,为了充分利用计算机CPU资源,一般开启多个线程来执行异步任务.但不管是继承Thread类还是实现Runnable接口,都无法获取任务执行的结果.JDK 5中引入了Callable和 ...

  9. java Future 模式

    考慮這樣一個情況,使用者可能快速翻頁瀏覽文件中,而圖片檔案很大,如此在瀏覽到有圖片的頁數時,就會導致圖片的載入,因而造成使用者瀏覽文件時會有停頓 的現象,所以我們希望在文件開啟之後,仍有一個背景作業持 ...

随机推荐

  1. 洛谷3934:Nephren Ruq Insania——题解

    https://www.luogu.org/problemnew/show/P3934 题面自己读吧(滑稽. 看到这道题就能够想到BZOJ4869:[SHOI2017]相逢是问候我们曾经用过的哲学扩展 ...

  2. 51NOD 1353:树——题解

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1353 今天小a在纸上研究树的形态,众所周知的,有芭蕉树,樟树,函树,平衡 ...

  3. UVA.548 Tree(二叉树 DFS)

    UVA.548 Tree(二叉树 DFS) 题意分析 给出一棵树的中序遍历和后序遍历,从所有叶子节点中找到一个使得其到根节点的权值最小.若有多个,输出叶子节点本身权值小的那个节点. 先递归建树,然后D ...

  4. JavaScript URL汉字编码转换

    在使用url进行参数传递时,经常会传递一些中文名的参数或URL地址,在后台处理时会发生转换错误.在有些传递页面使用GB2312,而在接收页面使用UTF8,这样接收到的参数就可能会与原来发生不一致.使用 ...

  5. UIView的autoresizingMask属性研究

    在 UIView 中有一个autoresizingMask的属性,它对应的是一个枚举的值(如下),属性的意思就是自动调整子控件与父控件中间的位置,宽高. 1 2 3 4 5 6 7 8 9 enum  ...

  6. Hadoop Yarn事件处理框架源码分析

    由于想在项目中使用类似yarn的事件处理机制,就看了实现.主要是由Dispatcher.java,EventHandler.java,Service.java这3个类撑起来的. 在事件处理之前,先注册 ...

  7. std::string在多字节字符集环境下substr的实现方法

    昨天写到<使用多字节字符集的跨平台(PC.Android.IOS.WP)编码/解码方法>中提到服务端使用std::string处理字符串,std::string对多字节字符集支持并不是很完 ...

  8. XSS攻击处理方案

    1. XSS攻击基本概念 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中.比如这些代码包括HTML代码和客户端脚本.攻击者利用XSS漏洞 ...

  9. c# 计算时间差---天数

    ---处理两个时间相差的天数 测试数据:三个时间 DateTime dt1 = Convert.ToDateTime("2017-03-17 09:49:55.667"); Dat ...

  10. mysql按月统计六个月内不同类型订单的成交金额

    mysql按月统计六个月内不同类型订单的成交金额 创建数据库 CREATE DATABASE test; 创建订单表 CREATE TABLE `t_order` ( `id` ) NOT NULL ...