【Java线程】Callable和Future
Future模式
Future接口是Java线程Future模式的实现,可以来进行异步计算。
Future模式可以这样来描述:
我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时间之后,我就便可以从Future那儿取出结果。
就相当于下了一张订货单,一段时间后可以拿着提订单来提货,这期间可以干别的任何事情。其中Future接口就是订货单,真正处理订单的是Executor类,它根据Future接口的要求来生产产品。
Callable和Future接口
Callable接口
Callable和Future一个产生结果,一个拿到结果。
Callable接口类似于Runnable,但是Runnable不会返回结果,而Callable可以返回结果,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值。
- V call()
- /**
- * Computes a result, or throws an exception if unable to do so.
- *
- * @return computed result
- * @throws Exception if unable to compute a result
- */
- V call() throws Exception;
Future接口
Future 表示异步计算的结果。Future接口中有如下方法:
- boolean cancel(boolean mayInterruptIfRunning)
取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束
- boolean isCancelled()
任务是否已经取消,任务正常完成前将其取消,则返回 true
- boolean isDone()
任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true
- V get()
等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationException
- V get(long timeout, TimeUnit unit)
同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计算超时,将抛出TimeoutException
Future接口提供方法来检测任务是否被执行完,等待任务执行完获得结果。也可以设置任务执行的超时时间,这个设置超时的方法就是实现Java程序执行超时的关键。
所以,如果需要设定代码执行的最长时间,即超时,可以用Java线程池ExecutorService类配合Future接口来实现。
- int result = future.get(5000, TimeUnit.MILLISECONDS);
Future实现类:SwingWorker
http://blog.csdn.net/vking_wang/article/details/8994882
Future实现类:FutureTask
Future的实现类有java.util.concurrent.FutureTask<V>即 javax.swing.SwingWorker<T,V>。通常使用FutureTask来处理我们的任务。
FutureTask类同时又实现了Runnable接口,所以可以直接提交给Thread、Executor执行。
- 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);// 可能做一些事情
- int result = future.get());
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- }
通过ExecutorService的submit方法执行Callable,并返回Future
使用ExecutorService:
- public class CallableAndFuture {
- public static void main(String[] args) {
- //ExecutorService.submit()
- 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);// 可能做一些事情
- int result = future.get()); //Future.get()
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- }
如果要执行多个带返回值的任务,并取得多个返回值,可用CompletionService:
CompletionService相当于Executor加上BlockingQueue,使用场景为当子线程并发了一系列的任务以后,主线程需要实时地取回子线程任务的返回值并同时顺序地处理这些返回值,谁先返回就先处理谁。
- 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;
- //CompletionService.submit()
- cs.submit(new Callable<Integer>() {
- public Integer call() throws Exception {
- return taskID;
- }
- });
- }
- // 可能做一些事情
- for(int i = 1; i < 5; i++) {
- try {
- int result = cs.take().get()); //CompletionService.take()返回Future
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
- }
- }
或者不使用CompletionService:先创建一个装Future类型的集合,用Executor提交的任务返回值添加到集合中,最后便利集合取出数据。
区别:
Future集合方法,submit的task不一定是按照加入自己维护的list顺序完成的。从list中遍历的每个Future对象并不一定处 于完成状态,这时调用get()方法就会被阻塞住,如果系统是设计成每个线程完成后就能根据其结果继续做后面的事,这样对于处于list后面的但是先完成 的线程就会增加了额外的等待时间。
而CompletionService的实现是维护一个保存Future对象的BlockingQueue。只 有当这个Future对象状态是结束的时候,才会加入到这个Queue中,take()方法其实就是Producer-Consumer中的 Consumer。它会从Queue中取出Future对象,如果Queue是空的,就会阻塞在那里,直到有完成的Future对象加入到Queue中。
所以,先完成的必定先被取出。这样就减少了不必要的等待时间。
【Java线程】Callable和Future的更多相关文章
- Java线程--Callable使用
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871727.html Java线程--Callable使用 Callable和Runnabl ...
- JDK5.0特性-线程 Callable和Future
来自:http://www.cnblogs.com/taven/archive/2011/12/17/2291466.html import java.util.concurrent.Callable ...
- java并发--Callable、Future和FutureTask
在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...
- Java多线程 - Callable和Future
已知的创建多线程的方法有继承Tread类和实现Runnable方法.此外Java还提供了Callable接口,Callable接口也提供了一个call()方法来做为线程执行体.但是call()方法与r ...
- Java Callable Future Example(java 关于Callable,Future的例子)
Home » Java » Java Callable Future Example Java Callable Future Example April 3, 2018 by Pankaj 25 C ...
- Java多线程Callable和Future类详解
public interface Callable<V> 返回结果并且可能抛出异常的任务.实现者定义了一个不带任何参数的叫做 call 的方法 public in ...
- JavaSE---多线程---Callable、Future
1.概述 1.1 JDK1.5后,Java提供了Callable接口,该接口提供一个call方法作为线程执行体,该call方法可以 有返回值.声明抛出异常: 因此,我们可以直接将Callable接口 ...
- Java多线程-Callable的Future返回值的使用
一般使用线程池执行任务都是调用的execute方法,这个方法定义在Executor接口中: public interface Executor { void execute(Runnable comm ...
- java多线程系类:JUC线程池:06之Callable和Future(转)
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...
随机推荐
- 边工作边刷题:70天一遍leetcode: day 86-1
Find Median from Data Stream 要点: 基本框架:两个heap:large,small把所有数二分.一个新的element.目标:维持heap中的元素个数相同.错误理解:新元 ...
- Trie树 & 01Trie
指针版 #define MAXNUM 26 //定义字典树结构体 typedef struct Trie { bool flag;//从根到此是否为一个单词 Trie *next[MAXNUM]; } ...
- UVA 11992 Fast Matrix Operations (二维线段树)
解法:因为至多20行,所以至多建20棵线段树,每行建一个.具体实现如下,有些复杂,慢慢看吧. #include <iostream> #include <cstdio> #in ...
- leetcode : valid binary search tree
不能通过 当元素中 有 val == INT_MAX 或者 val == INT_MIN /** * Definition for a binary tree node. * struct Tree ...
- JavaWeb学习之Servlet(一)----MyEclipse及Tomcat的配置
[声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4134921.html [开发环境] 物理机版本:Win 7旗舰版(64位 ...
- Unity-WIKI 之 DebugConsole
功能预览 使用说明 1.把 DebugConsole.cs 放在 Standard Assets 目录下(重要) 2.如果你想修改 DebugConsole的一些参数,把DebugConsole.cs ...
- Windows server 2008系统基本优化
前几天用上了Windows server 2008刚开始还真不习惯,毕竟是做服务器用的系统和娱乐操作系统有很大区别.先总结几点,以后慢慢更新 安装Win2008驱动: 大部分支持vista系统的驱动都 ...
- C#定制并发送HTML邮件
HTML格式的邮件能够使用所有html/css使得邮件更丰富,比如现在很多newsletter 都是使用的html邮件. 今天试了一下,如何把图片嵌入到html中呢? 方法一,你的图片host到了in ...
- 使用eclipse+tomcat搭建本地环境
项目开发工具很多,这里简单介绍下使用eclipse+tomcat如何搭建本地环境. 安装开发工具如下: 1. jdk的安装参考 下载地址:http://pan.baidu.com/s/1sj9rVYX ...
- GEOS库学习之五:与GDAL/OGR结合使用
要学习GEOS库,肯定绕不开地理方面的东西.如果需要判断的两个多边形或几何图形,不是自己创建的,而是来自shapefile文件,那就得将GEOS库和GDAL/OGR库结合使用了.实际上只需要OGR就行 ...