接着上一篇继续并发包的学习,本篇说明的是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提交的任务返回值添加到集合中,最后遍历集合取出数据,代码略。更新于2016-02-05,评论中就这个说法引发了讨论,其实是我没有讲清楚,抱歉。这里再阐述一下:提交到CompletionService中的Future是按照完成的顺序排列的,这种做法中Future是按照添加的顺序排列的。所以这两种方式的区别就像评论中fishjam所描述的那样。

本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7451464,转载请注明。

Java线程:Callable和Future的更多相关文章

  1. Java线程--Callable使用

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11871727.html Java线程--Callable使用 Callable和Runnabl ...

  2. JDK5.0特性-线程 Callable和Future

    来自:http://www.cnblogs.com/taven/archive/2011/12/17/2291466.html import java.util.concurrent.Callable ...

  3. java并发--Callable、Future和FutureTask

    在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...

  4. Java多线程 - Callable和Future

    已知的创建多线程的方法有继承Tread类和实现Runnable方法.此外Java还提供了Callable接口,Callable接口也提供了一个call()方法来做为线程执行体.但是call()方法与r ...

  5. Java Callable Future Example(java 关于Callable,Future的例子)

    Home » Java » Java Callable Future Example Java Callable Future Example April 3, 2018 by Pankaj 25 C ...

  6. Java多线程Callable和Future类详解

         public interface Callable<V>    返回结果并且可能抛出异常的任务.实现者定义了一个不带任何参数的叫做 call 的方法      public in ...

  7. JavaSE---多线程---Callable、Future

    1.概述 1.1 JDK1.5后,Java提供了Callable接口,该接口提供一个call方法作为线程执行体,该call方法可以  有返回值.声明抛出异常: 因此,我们可以直接将Callable接口 ...

  8. Java多线程-Callable的Future返回值的使用

    一般使用线程池执行任务都是调用的execute方法,这个方法定义在Executor接口中: public interface Executor { void execute(Runnable comm ...

  9. java多线程系类:JUC线程池:06之Callable和Future(转)

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  10. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

随机推荐

  1. 如何用 CSS 绘制各种形状

    自适应的椭圆 1.自适应的椭圆 实现方式是通过border-radius这个属性:border-radius它可以单独指定水平和垂直半径.用 / 分隔这两个值.并且该属性的值不仅可以接受长度值,还能接 ...

  2. LOL喷子专用自动骂人工具,2018更新完整版!

    软件截图 软件说明: 先进入游戏 打开程序 Z开启/C关闭 下载地址:密码 yjnm

  3. 迅为IMX6核心板开发平台智能交通解决方案

    智能交通系统它是将先进的信息技术.数据通讯传输技术.电子传感技术.控制技术及计算机技术等有效地集成运用于整个地面交通管理系统而建立的一种在大范围内.全方位发挥作用的,实时.准确.高效的综合交通运输管理 ...

  4. Google浏览器开发者工具:CSSViewer(一个Css查看器)

    CSSViewer的简介 CSSViewer是一款可以帮助用户快速查看当前的网页元素的CSS属性的谷歌浏览器插件,在Chrome中安装了CSSViewer插件以后,用户就可以在设计网页的时候,快速地模 ...

  5. 自动交互脚本之expect使用记录

    之前一直没怎么用这个命令,意外用了一下,还不错,那这个是干嘛的呢 我们或多或少会远程登录其他服务器,需要执行某项任务,通常需要手动接入,输入密码啊,等等 那我们如何有效的自动执行呢,expect可以解 ...

  6. Java B

    3.继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么? 答:父类: package test; public class FatherClass { public FatherClass( ...

  7. JavaSE-12 面向对象程序设计的几条基础原则

    摘取代码中变化的行为,形成接口 在设计基类的时候,如果该类某个成员方法在子类中的实现变化差别比较大(一部分子类实现该方法是相同的),作为基类有两个问题:一是该方法不再通用:二是子类如果重写该方法,存在 ...

  8. 根据数据库表自动生成实体类、xml和dao---mybatis

    网盘链接: https://pan.baidu.com/s/1AVGz0bDa_Y5zjk7vXa2eHw 提取码: 2gr6 1.记事本打开generatorConfig.xml文件 2(1,2,3 ...

  9. oracle分析函数系列之sum(col1) over(partition by col2 order by col3):实现分组汇总或递增汇总

    语法:sum(col1) over(partition by col2 order by col3 )  准备数据: DEPT_ID    ENAME          SAL1 1000       ...

  10. 诊断:CLSRSC-400: A system reboot is required to continue installing.

    Linux7.5安装Grid Infrastructure 12.2.0.1时,在root.sh时会报错 2018/01/30 09:19:28 CLSRSC-330: Adding Clusterw ...