携带结果的任务

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)带返回结果的任务执行的更多相关文章

  1. Java并发专题 带返回结果的批量任务运行 CompletionService ExecutorService.invokeAll

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 普通情况下,我们使用Runnable作为主要的任务表示形式,可是R ...

  2. Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll(转)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 一般情况下,我们使用Runnable作为基本的任务表示形式,但是R ...

  3. Java并发专题 带返回结果的批量任务执行

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/27250059 一般情况下,我们使用Runnable作为基本的任务表示形式,但是R ...

  4. 《Java并发编程实战》学习笔记 任务执行和取消关闭

    查看豆瓣读书 第六章 任务执行 大多数并发应用程序是围绕执行任务进行管理的.设计任务时,要为任务设计一个清晰的任务边界,并配合一个明确的任务执行策略.任务最好是独立的,因为这会提高并发度.大多数服务器 ...

  5. (转)Java并发编程:线程池的使用

    背景:线程池在面试时候经常遇到,反复出现的问题就是理解不深入,不能做到游刃有余.所以这篇博客是要深入总结线程池的使用. ThreadPoolExecutor的继承关系 线程池的原理 1.线程池状态(4 ...

  6. Java并发编程专题

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. http://www.cnblogs.com/shijiaqi1066/p/4852149. ...

  7. 慕课网-Java入门第一季-7-3 Java 中无参带返回值方法的使用

    来源:http://www.imooc.com/code/1579 如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值 ...

  8. Java 中带参带返回值方法的使用

    如果方法既包含参数,又带有返回值,我们称为带参带返回值的方法. 例如:下面的代码,定义了一个 show 方法,带有一个参数 name ,方法执行后返回一个 String 类型的结果 调用带参带返回值的 ...

  9. Java 中无参带返回值方法的使用

    如果方法不包含参数,但有返回值,我们称为无参带返回值的方法. 例如:下面的代码,定义了一个方法名为 calSum ,无参数,但返回值为 int 类型的方法,执行的操作为计算两数之和,并返回结果 在 c ...

随机推荐

  1. dom操作之开关灯

    <!DOCTYPE html> <html> <meta http-equiv="Content-Type" content="text/h ...

  2. [Hadoop源码解读](四)MapReduce篇之Counter相关类

    当我们定义一个Counter时,我们首先要定义一枚举类型: public static enum MY_COUNTER{ CORRUPTED_DATA_COUNTER, NORMAL_DATA_COU ...

  3. MFC CVIew关闭时崩溃

    记得看视频的时候老师说过    创建CView的时候,也就是创建视图的时候,不要使用  Cview      m_view;这种方式 而是使用Cview  *  pView=new   Cview() ...

  4. [HDU POJ] 逆序数

    HDU 1394 Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/3276 ...

  5. 布隆过滤器(Bloom Filter)的原理和实现

    什么情况下需要布隆过滤器? 先来看几个比较常见的例子 字处理软件中,需要检查一个英语单词是否拼写正确 在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上 在网络爬虫里,一个网址是否被访问过 yahoo, ...

  6. while MyJob = '程序员' do --- 序

    因为自己的际遇,忽然想写点什么留在这个世上.也许只是想证明自己活过吧. 所以,这不会是一个过去时的小说,这将是一个接近进行时的记叙.之所以是接近,因为我只有在空余时间,才能记录最近的经历.出于保护隐私 ...

  7. NOIP2002 矩形覆盖

    题四 矩形覆盖(存盘名NOIPG4) [问题描述]: 在平面上有 n 个点(n <= 50),每个点用一对整数坐标表示.例如:当 n=4 时,4个点的坐标分另为:p1(1,1),p2(2,2), ...

  8. 关于FP-Growth 算法一个很好的ppt-学习分享

    http://pan.baidu.com/share/link?shareid=1980963149&uk=1594824745

  9. 【解决】exited with a non-zero exit code 1

      安装好集群后运行hadoop-mapreduce-examples.jar 报错,比对cdh配置后,发现少了yarn.application.classpath,conf目录一定要配置,否则也会出 ...

  10. Kooboo 加Search功能 必须先ReBuild Index Data

      加Search功能   有几个要点 1. 需要在Kooboo 必须先 ReBuild Index Data 2. 需要在要搜索的page中启用搜索索引         搜索的代码 @using K ...