Java并发编程之Callable, Runnable, Future, FutureTask

  Java中存在Callable, Runnable, Future, FutureTask这几个与线程相关的类或接口, 下面来了解一下它们的作用和区别.

一.Callable和Runnable

  Callable和Runnable类似, 实现Callable和Runnable接口的类都是可以被其他线程运行的任务, Callable和Runnable主要有以下几点区别:

(1). Callable中声明的方法是call(), Runnable中声明的方法是run().

(2). Callable任务执行后可返回值, Runnable任务执行后没有返回值.

(3). call()方法可以抛出异常, run()方法不能抛出异常.

(4). 运行Callable任务可以拿到一个Future对象.

 public interface Callable<V> {
     /**
      * 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;
 }

 public interface Runnable {
     /**
      * When an object implementing interface <code>Runnable</code> is used
      * to create a thread, starting the thread causes the object's
      * <code>run</code> method to be called in that separately executing
      * thread.
      * <p>
      * The general contract of the method <code>run</code> is that it may
      * take any action whatsoever.
      *
      * @see     java.lang.Thread#run()
      */
     public abstract void run();
 }

二. Future对象

  Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。可以通过get()方法获取执行结果, get()方法会阻塞,直到任务返回结果

public interface Future<V> {

    /**
     * Attempts to cancel execution of this task.  This attempt will
     * fail if the task has already completed, has already been cancelled,
     * or could not be cancelled for some other reason. If successful,
     * and this task has not started when <tt>cancel</tt> is called,
     * this task should never run.  If the task has already started,
     * then the <tt>mayInterruptIfRunning</tt> parameter determines
     * whether the thread executing this task should be interrupted in
     * an attempt to stop the task.
     *
     * <p>After this method returns, subsequent calls to {@link #isDone} will
     * always return <tt>true</tt>.  Subsequent calls to {@link #isCancelled}
     * will always return <tt>true</tt> if this method returned <tt>true</tt>.
     *
     * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
     * task should be interrupted; otherwise, in-progress tasks are allowed
     * to complete
     * @return <tt>false</tt> if the task could not be cancelled,
     * typically because it has already completed normally;
     * <tt>true</tt> otherwise
     */
    boolean cancel(boolean mayInterruptIfRunning);

    /**
     * Returns <tt>true</tt> if this task was cancelled before it completed
     * normally.
     */
    boolean isCancelled();

    /**
     * Returns <tt>true</tt> if this task completed.
     * Completion may be due to normal termination, an exception, or
     * cancellation -- in all of these cases, this method will return
     * <tt>true</tt>.
     */
    boolean isDone();

    /**
     * Waits if necessary for the computation to complete, and then
     * retrieves its result.
     */
    V get() throws InterruptedException, ExecutionException;

    /**
     * Waits if necessary for at most the given time for the computation
     * to complete, and then retrieves its result, if available.
     */
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

下面依次解释每个方法的作用:

  • cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数 mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如 果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返 回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若 mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论 mayInterruptIfRunning为true还是false,肯定返回true。
  • isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
  • isDone方法表示任务是否已经完成,若任务完成,则返回true;
  • get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
  • get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。

  也就是说Future提供了三种功能:

  1)判断任务是否完成;

  2)能够中断任务;

  3)能够获取任务执行结果。

  因为Future只是一个接口,所以是无法直接用来创建对象使用的,因此就有了下面的FutureTask。

三. FutureTask

  我们先来看一下FutureTask的实现:

public class FutureTask<V> implements RunnableFuture<V> {

}

  FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:

public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

  可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。

  FutureTask提供了2个构造器:

public FutureTask(Callable<V> callable) {
    }

public FutureTask(Runnable runnable, V result) {
    }

事实上,FutureTask是Future接口的一个唯一实现类

简单示例:

import java.util.concurrent.*;

/**
 * Created by xinfengyao on 16-2-17.
 */
public class RunnableFutureTest {
    static ExecutorService executorService = Executors.newCachedThreadPool();

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        runnableDemo();
        futureDemo();
    }

    /**
     * Runnable无返回值
     */
    static void runnableDemo() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("runnable demo: " + fibc(20));
            }
        }).start();
    }

    /**
     * 其中Runnable实现的是void run()方法,无返回值;Callable实现的是 V
     * call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下
     * ,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。
     */
    static void futureDemo() throws ExecutionException, InterruptedException {
        /**
         * 提交runnable则没有返回值, future没有数据
         */
        Future<?> result = executorService.submit(new Runnable() {
            @Override
            public void run() {
                fibc(20);
            }
        });
        System.out.println("future result from runnable: " + result.get());

        /**
         * 提交Callable, 有返回值, future中能够获取返回值
         */
        Future<Integer> result2 = executorService.submit(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return fibc(20);
            }
        });
        System.out.println("future result from callable: " + result2.get());

        /**
         * FutureTask则是一个RunnableFuture<V>,既实现了Runnable又实现了Future<V>这两个接口,
         * 另外它还可以包装Runnable(实际上会转换为Callable)和Callable
         * <V>,所以一般来讲是一个复合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行
         * ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。
         */
        FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return fibc(20);
            }
        });
        // 提交futureTask
        executorService.submit(futureTask);
        System.out.println("future result from futureTask: " + futureTask.get());
    }

    static int fibc(int n) {
        if (n==0 || n==1) {
            return n;
        }
        return fibc(n-1) + fibc(n-2);
    }

}

运行结果:

runnable demo: 6765
future result from runnable: null
future result from callable: 6765
future result from futureTask: 6765

Callable, Runnable, Future, FutureTask的更多相关文章

  1. Callable和Future、FutureTask的使用

    http://www.silencedut.com/2016/06/15/Callable%E5%92%8CFuture%E3%80%81FutureTask%E7%9A%84%E4%BD%BF%E7 ...

  2. Runnable、Callable、Future和FutureTask用法

    http://www.cnblogs.com/dolphin0520/p/3949310.html java 1.5以前创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable ...

  3. Java中的Runnable、Callable、Future、FutureTask的区别

    本文转载自:http://blog.csdn.net/bboyfeiyu/article/details/24851847 Runnable 其中Runnable应该是我们最熟悉的接口,它只有一个ru ...

  4. 多线程-Thread,Runnable,Callable,Future,RunnableFuture,FutureTask

    类图: 先看各自的源码: public interface Runnable { public abstract void run(); } public class Thread implement ...

  5. Runnable、Callable、Future和FutureTask之一:基本用法

    Java从发布的第一个版本开始就可以很方便地编写多线程的应用程序,并在设计中引入异步处理.Thread类.Runnable接口和Java内存管理模型使得多线程编程简单直接.但正如之前提到过的,Thre ...

  6. Runnable、Callable、Future和FutureTask之二:源码解析

    一.Callable与Future类图 1.类图 许多任务实际上都是存在延迟的计算,对于这些任务,Callable是一种更好的抽象:它会返回一个值,并可能抛出一个异常.Callable接口: V ca ...

  7. Java中的Runnable、Callable、Future、FutureTask的区别与示例

    Java中存在Runnable.Callable.Future.FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别. ...

  8. Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask

    多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread.Runnable.Callable.Future.FutureTask这几个类往往是初学者容易搞混的. ...

  9. Java并发编程:Callable、Future和FutureTask

    作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置 ...

随机推荐

  1. window.cookie

    本地测试cookie用火狐来测试 首先cookie是document上的一个属性. 先弹出一个cookie alert(document.cookie); //弹出是空的 设置cookie,格式是有一 ...

  2. csuoj 1111: 三家人

    acm.csu.edu.cn/OnlineJudge/problem.php?id=1111 1111: 三家人 Time Limit: 1 Sec  Memory Limit: 128 MBSubm ...

  3. java dom4j写入XML

    引用的两个jar包 dom4j-1.6.1.jar jaxen.jar //=========================代码 import java.io.FileWriter;import j ...

  4. SpringMVC配制全局的日期格式

    SpringMVC文件配制: <mvc:annotation-driven> <!-- 处理responseBody 里面日期类型 --> <mvc:message-co ...

  5. Multi-voltage和power gating的实现

    power domain:一个逻辑的集合体,包含power supply的一些信息.建立在FE. voltage area:chip上的一块物理区域.可以看作power domain的物理实现. Le ...

  6. MySQL增删改查

    C/S:Client ServerB/S:Brower Server php主要实现B/S .net IIS java TomCat LAMP: Linux系统 A阿帕奇服务器 Mysql数据库 Ph ...

  7. 关于archlinux下的ralink5370网卡

    驱动此网卡要使用 rt2800usb,rt2800lib 这两个模块 顺便说一下对模块进行操作的命令: rmmod 模块名 //为移除模块 insmod 模块所在路径 //为添加模块 查看网卡是否能被 ...

  8. 【py网页】sitecopy代码

    001 #coding:utf-8 002 import re,os,shutil,sys 003 import urllib2,socket,cookielib 004 from threading ...

  9. Visual studio 中编译错误SQL71006: Only one statement is allowed per batch. A batch separator, such as 'GO', might be required between statements.

    把写好的sql脚本,并在mssqlmanager里面编译成功的存储过程脚本复制到vs项目下,出现错误信息如下:SQL71006: Only one statement is allowed per b ...

  10. Sublime怎样新建HTML文档

    1.在右下角有个plain text的标志,点击,选择文件类型为HTML 2.保存为HTML文档 3.这时候输入"!"(注意一定要选择对输入法) 4.然后按"Tab&qu ...