Java并发(6)带返回结果的任务执行
携带结果的任务
JDK5提供了有可返回值的任务的执行。java.util.concurrent中Callable与Futrue用以实现带返回值的任务执行。
使用Callable与Futrue与使用Runnable最大的两个区别在于:
1、Callable/Future是带返回值的;Runnable无法带返回值。
2、Callable/Future所执行的任务是可取消的。Runnable的任务无法取消。

Callable接口
Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。可返回值的任务必须实现Callable接口。
public interface Callable<V> {
V call() throws Exception;
}
call()方法用于计算结果,如果无法计算结果,则抛出一个异常。V是call方法的结果类型。
Callable接口定义了一个call方法可以作为线程的执行体,但call方法比run方法更强大:
call()方法可以有返回值。
call()方法可以申明抛出异常。
通过ExecutorSevice的submit()方法将Callable提交至线程池中执行,submit()方法返回一个Future实例。
使用CompletionService接口可以用于提交一组Callable任务,其take()方法返回已完成的一个Callable任务对应的Future实例。好比同时种了几块地的麦子,然后就等待收割。收割时,则是那块先成熟了,则先去收割哪块麦子。
Futrue接口
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。
一旦计算完成,就不能再取消计算。
提交(submit()方法)Callable任务,可以获取一个Future实例。Futrue实例调用get()方法即可获取Callable任务返回值。
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
Future接口里定义了如下几个公共方法控制他关联的Callable任务:
V get():返回Callable任务里的call()方法的返回值,调用该方法将导致线程阻塞,必须等到子线程结束才得到返回值。
V get(long timeout,TimeUnit unit) : 返回Callable任务里的call方法的返回值。该方法让程序最多阻塞timeout和unit指定的时间。如果经过指定时间后Callable任务依然没有返回值,将会抛出TimeoutException。
boolean cancel(boolean mayInterruptlfRunning) :试图取消该Future里关联的Callable任务。
boolean isCancelled() :如果在Callable任务正常完成前被取消,则返回true。
boolean isDone() :如果Callable任务已经完成,则返回true。
例:使用Executor框架执行Callable并返回结果。
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.*;
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
// 创建两个有返回值的任务
Callable c1 = new MyCallable("A");
Callable c2 = new MyCallable("B");
// 执行任务并获取Future对象
Future f1 = pool.submit(c1);
Future f2 = pool.submit(c2);
// 从Future对象上获取任务的返回值,并输出到控制台
System.out.println(">>>" + f1.get().toString());
System.out.println(">>>" + f2.get().toString());
// 关闭线程池
pool.shutdown();
}
}
class MyCallable implements Callable {
private String oid;
MyCallable(String oid) {
this.oid = oid;
}
@Override
public Object call() throws Exception {
return oid + "任务返回的内容";
}
}
执行输出结果:
>>>A任务返回的内容
>>>B任务返回的内容
RunnableFuture接口
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
FutrueTask类
java.util.concurrent.FutureTask<V>
Future接口的一个实现类。该实现类实现Future接口,并实现了Runnable接口。FutureTask即可以作为Thread的target。
使用FutrueTask执行单个任务。
创建、并启动有返回值的线程的步骤如下:
1.创建Callable接口的实现类,实现call方法。
2.创建Callable实现类的实例,使用FutureTask类来包装Callable对象。
3.使用FutureTask对象作为Thread对象的target创建、并启动新线程。
4.调用FutureTask对象的方法来获得子线程执行结束后的返回值。
例:使用FutrueTask类执行Callable并返回结果。
class RtnThread implements Callable<Integer> {
public Integer call() {
// 执行过程
}
}
public class CallableTest {
public static main(String[] args) {
// 创建Callable对象。
RtnThread rt = new RtnThread();
FutureTask<Integer> task = new FutureTask<Integer>(rt);
// ..
// 创建线程,并启动。
new Thread(task).start();
// ..
Integer i = task.get(); // 获取线程返回值。
}
}
创建Callable实现类与创建Runnable实现类并没有太大差别,只是Callable的call允许抛出异常,而且允许带返回值。
Java并发(6)带返回结果的任务执行的更多相关文章
- Java并发专题 带返回结果的批量任务运行 CompletionService ExecutorService.invokeAll
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 普通情况下,我们使用Runnable作为主要的任务表示形式,可是R ...
- Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll(转)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 一般情况下,我们使用Runnable作为基本的任务表示形式,但是R ...
- Java并发专题 带返回结果的批量任务执行
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 一般情况下,我们使用Runnable作为基本的任务表示形式,但是R ...
- 《Java并发编程实战》学习笔记 任务执行和取消关闭
查看豆瓣读书 第六章 任务执行 大多数并发应用程序是围绕执行任务进行管理的.设计任务时,要为任务设计一个清晰的任务边界,并配合一个明确的任务执行策略.任务最好是独立的,因为这会提高并发度.大多数服务器 ...
- (转)Java并发编程:线程池的使用
背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...
- Java并发编程专题
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/4852149. ...
- 慕课网-Java入门第一季-7-3 Java 中无参带返回值方法的使用
来源:http://www.imooc.com/code/1579 如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值 ...
- Java 中带参带返回值方法的使用
如果方法既包含参数,又带有返回值,我们称为带参带返回值的方法. 例如:下面的代码,定义了一个 show 方法,带有一个参数 name ,方法执行后返回一个 String 类型的结果 调用带参带返回值的 ...
- Java 中无参带返回值方法的使用
如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值为 int 类型的方法,执行的操作为计算两数之和,并返回结果 在 c ...
随机推荐
- Linux Kernel本地权限提升漏洞
漏洞版本: Linux Kernel 漏洞描述: Bugtraq ID:64291 CVE ID:CVE-2013-6368 Linux Kernel是一款开源的操作系统. 如果用户空间提供的vapi ...
- BZOJ2348: [Baltic 2011]Plagiarism
2348: [Baltic 2011]Plagiarism Time Limit: 1 Sec Memory Limit: 256 MBSubmit: 304 Solved: 141[Submit ...
- NOI 2014 感想
NOI2014结束了,我卡线登上了领奖台... 这是我第一次NOI,我觉得我收获了很多东西: 1.考前心态不重要,重要的是实力 真正考试的时候是顾不得想其他事情的 2.测试数据是人出的!不是随机的!不 ...
- apache和tomcat
Apache 和 Tomcat 都是web网络服务器,两者既有联系又有区别,在进行HTML.PHP.JSP.Perl等开发过程中,需要准确掌握其各自特点,选择最佳的服务器配置. Apache是web服 ...
- 从头开始编写一个Orchard网上商店模块(4) - 创建ProductPart
原文地址:http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-par ...
- C# 深复制
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...
- lua package.path的使用
需要用lua写一个工具,c++调用lua,然后这个lua要require其他lua脚本,在主lua里面设置package.path,但一直都失败,甚至lua都无法编译通过. project_path ...
- leetcode之Palindrome Partitioning
方法一:DFS递归,判断每一个是否为回文数 1,首先要有一个判断字符串是否是回文的函数.容易实现,字符串从两边同时往中间走,看字符是否相同; 2,深度优先搜索思想对字符串进行遍历.得到结果.例如,s ...
- bzoj 3033 太鼓达人
思路:首先一定是2^m次方的总数.用二进制从 000 一直到 111总过m个数,然后暴搜. #include<cstdio> #include<cstring> #includ ...
- FZU Problem 2125 简单的等式
思路:x绝对小于根号n,再由s(x,m)可以缩小范围.1e9十六进制大约算出每位和相加100左右.这种题直接判断范围再暴力. #include<stdio.h> #include<s ...