Callable接口和Future
本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果。
Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值,下面来看一个简单的例子:
public class CallableAndFuture {
public static void main(String[] args) {
Callable<Integer> callable = new Callable<Integer>() {
public Integer call() throws Exception {
return new Random().nextInt(100);
}
};
FutureTask<Integer> future = new FutureTask<Integer>(callable);
new Thread(future).start();
try {
Thread.sleep(5000);// 可能做一些事情
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值,那么这个组合的使用有什么好处呢?假设有一个很耗时的返回值需要计算,并且这个返回值不是立刻需要的话,那么就可以使用这个组合,用另一个线程去计算返回值,而当前线程在使用这个返回值之前可以做其它的操作,等到需要这个返回值时,再通过Future得到,岂不美哉!这里有一个Future模式的介绍:http://openhome.cc/Gossip/DesignPattern/FuturePattern.htm。
下面来看另一种方式使用Callable和Future,通过ExecutorService的submit方法执行Callable,并返回Future,代码如下:
public class CallableAndFuture {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<Integer> future = threadPool.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return new Random().nextInt(100);
}
});
try {
Thread.sleep(5000);// 可能做一些事情
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
代码是不是简化了很多,ExecutorService继承自Executor,它的目的是为我们管理Thread对象,从而简化并发编程,Executor使我们无需显示的去管理线程的生命周期,是JDK 5之后启动任务的首选方式。
执行多个带返回值的任务,并取得多个返回值,代码如下:
public class CallableAndFuture {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newCachedThreadPool();
CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool);
for(int i = 1; i < 5; i++) {
final int taskID = i;
cs.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return taskID;
}
});
}
// 可能做一些事情
for(int i = 1; i < 5; i++) {
try {
System.out.println(cs.take().get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
其实也可以不使用CompletionService,可以先创建一个装Future类型的集合,用Executor提交的任务返回值添加到集合中,最后遍历集合取出数据
参考代码:
package com.jd.test; import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*; public class CallableTest4 {
public static void main(String[] args) {
ExecutorService es= Executors.newCachedThreadPool();
List<Future<Integer>> futureList=new ArrayList<Future<Integer>>();
for(int i=0;i<10;i++) {
Future<Integer> integerFuture = es.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return new Random().nextInt(100);
}
});
futureList.add(integerFuture);
}
try {
System.out.println("系统兼职开始~");
Thread.sleep(5000);// 可能做一些事情
System.out.println("系统兼职结束~");
for(Future<Integer> futureInteger:futureList){
System.out.println("回到先前的任务 随机数为:"+futureInteger.get());
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
提交到CompletionService中的Future是按照完成的顺序排列的,而Lisr这种做法中Future是按照添加的顺序排列的。
参考链接:http://blog.csdn.net/ghsau/article/details/7451464
Callable接口和Future的更多相关文章
- Java Callable接口与Future接口的两种使用方式
Java Callable.Future的两种使用方式Callable+Futurepublic class Test { public static void main(String[] args) ...
- Callable接口、Runable接口、Future接口
1. Callable与Runable区别 Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理.Thread类.Runnable接口和Java内存管理模型使得多线 ...
- Java Callable接口、Runable接口、Future接口
1. Callable与Runable区别 Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理.Thread类.Runnable接口和Java内存管理模型使得多线 ...
- Future接口和Callable接口以及FeatureTask详解
类继承关系 Callable接口 @FunctionalInterface public interface Callable<V> { V call() throws Exception ...
- 实现Callable接口,并与Future结合使用
实现步骤: 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值. 创建 Callable 实现类的实例,使用 FutureTask ...
- 线程池的应用及Callable接口的使用
public interface Executor { /** * Executes the given command at some time in the future. The comman ...
- [改善Java代码]异步运算考虑使用Callable接口
多线程有两种实现方式: 一种是实现Runnable接口,另一种是继承Thread类,这两种方式都有缺点,run方法没有返回值,不能抛出异常(这两个缺点归根到底是Runable接口的缺陷,Thread也 ...
- 多线程——实现Callable接口
前两篇博客(多线程--继承Thread类.多线程--实现Runnable接口 )介绍了java使用线程的两种方法.这篇博客继续介绍第三种方法--实现Callable接口. 先说一下Runnable和C ...
- Java多线程之Callable接口的实现
Callable 和 Future接口 Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务. Callable和Runn ...
随机推荐
- js 压缩 预览 上传图片
com.js export const compressImage=function (files,fn,preCallbackFn,i) { let newfile = files.files[0] ...
- Foundation--NSString , array and Dictionary
一,NSString的创建 NSString*str=@" a string ";//直接创建一个字符串常量,这样创建出来的字符串不需要释放内存 NSLog(@"%@&q ...
- 5.1 socket编程、简单并发服务器
什么是socket? socket可以看成是用户进程与内核网络协议栈的编程接口.是一套api函数. socket不仅可以用于本机的进程间通信,还可以用于网络上不同主机间的进程间通信. 工业上使用的为t ...
- PHP发明人谈MVC和网站设计架构
PHP是全世界上使用率最高的网页开发语言,台湾每4个网站,就有1个用PHP语言开发.1995年发明PHP语言的Rasmus Lerdorf,也是打造出Yahoo全球服务网站的架构师之一,他首度来台分享 ...
- Jsonp的实现
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题. 由于同源策略,一般来说位于 server1.com 的网页无法与不是 serv ...
- 【图文教程】win7+VMware8.0+CentOS6.4 NAT上网
在win7下面安装VM8.0,里面又安装多个虚拟机,各个虚拟机之间可以互相访问,同时虚拟机可以直接访问外网上网,win7要ping通个虚拟机中的系统.这种方式就使用NAT模式,开启VMware Net ...
- linux环境下编译php扩展
1.使用ext_skel工具生成扩展框架 ./ext_skel --extname=myext 2.编辑config.m4文件 cd myext/vim config.m4 去掉以下内容的注释: PH ...
- Windows 10中更新Anaconda和第三方包
=============================== 作为专业的Python开发者,Anaconda包肯定很熟悉 下面总结一下Anaconda的升级和维护 步骤一: 打开cmd,切换到Ana ...
- 使用OASGraph 暴露rest 接口为graphql api
OASGraph 是loopback 团队开发的方便将rest api 暴露为graphql 的工具, 这个也是loopback 4 的一个新特性类似的有些团队提出了binding 以及stitch ...
- SQL Server 中关于EXCEPT和INTERSECT的用法
熟练使用SQL Server中的各种用法会给查询带来很多方便.今天就介绍一下EXCEPT和INTERSECT.注意此语法仅在SQL Server 2005及以上版本支持. EXCEPT是指在第一个集合 ...