zoukankan      html  css  js  c++  java
  • Java中的Runnable、Callable、Future、FutureTask的区别

    本文转载自:http://blog.csdn.net/bboyfeiyu/article/details/24851847

    Runnable

    其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中,该函数没有返回值。然后使用某个线程去执行该runnable即可实现多线程,Thread类在调用start()函数后就是执行的是Runnable的run()函数。Runnable的声明如下 : 

     1 public interface Runnable {
     2     /**
     3      * When an object implementing interface <code>Runnable</code> is used
     4      * to create a thread, starting the thread causes the object's
     5      * <code>run</code> method to be called in that separately executing
     6      * thread.
     7      * <p>
     8      *
     9      * @see     java.lang.Thread#run()
    10      */
    11     public abstract void run();
    12 }

    Callable 

    Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,而Runnable的run()函数不能将结果返回给客户程序。Callable的声明如下 :

    1 public interface Callable<V> {
    2     /**
    3      * Computes a result, or throws an exception if unable to do so.
    4      *
    5      * @return computed result
    6      * @throws Exception if unable to compute a result
    7      */
    8     V call() throws Exception;
    9 }

    可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的V类型。

    Future

    Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行

    取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(Future简介)。Future声明如下 :

     1 /**
     2 * @see FutureTask
     3  * @see Executor
     4  * @since 1.5
     5  * @author Doug Lea
     6  * @param <V> The result type returned by this Future's <tt>get</tt> method
     7  */
     8 public interface Future<V> {
     9 
    10     /**
    11      * Attempts to cancel execution of this task.  This attempt will
    12      * fail if the task has already completed, has already been cancelled,
    13      * or could not be cancelled for some other reason. If successful,
    14      * and this task has not started when <tt>cancel</tt> is called,
    15      * this task should never run.  If the task has already started,
    16      * then the <tt>mayInterruptIfRunning</tt> parameter determines
    17      * whether the thread executing this task should be interrupted in
    18      * an attempt to stop the task.     *
    19      */
    20     boolean cancel(boolean mayInterruptIfRunning);
    21 
    22     /**
    23      * Returns <tt>true</tt> if this task was cancelled before it completed
    24      * normally.
    25      */
    26     boolean isCancelled();
    27 
    28     /**
    29      * Returns <tt>true</tt> if this task completed.
    30      *
    31      */
    32     boolean isDone();
    33 
    34     /**
    35      * Waits if necessary for the computation to complete, and then
    36      * retrieves its result.
    37      *
    38      * @return the computed result
    39      */
    40     V get() throws InterruptedException, ExecutionException;
    41 
    42     /**
    43      * Waits if necessary for at most the given time for the computation
    44      * to complete, and then retrieves its result, if available.
    45      *
    46      * @param timeout the maximum time to wait
    47      * @param unit the time unit of the timeout argument
    48      * @return the computed result
    49      */
    50     V get(long timeout, TimeUnit unit)
    51         throws InterruptedException, ExecutionException, TimeoutException;
    52 }

    FutureTask

    FutureTask则是一个RunnableFuture<V>,而RunnableFuture实现了Runnbale又实现了Futrue<V>这两个接口,

     

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

     

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

    另外它还可以包装Runnable和Callable<V>, 由构造函数注入依赖。

     

     1     public FutureTask(Callable<V> callable) {
     2         if (callable == null)
     3             throw new NullPointerException();
     4         this.callable = callable;
     5         this.state = NEW;       // ensure visibility of callable
     6     }
     7 
     8     public FutureTask(Runnable runnable, V result) {
     9         this.callable = Executors.callable(runnable, result);
    10         this.state = NEW;       // ensure visibility of callable
    11     }
     可以看到,Runnable注入会被Executors.callable()函数转换为Callable类型,即FutureTask最终都是执行Callable类型的任务。该适配函数的实现如下 :

    RunnableAdapter适配器

     

     1     /**
     2      * A callable that runs given task and returns given result
     3      */
     4     static final class RunnableAdapter<T> implements Callable<T> {
     5         final Runnable task;
     6         final T result;
     7         RunnableAdapter(Runnable task, T result) {
     8             this.task = task;
     9             this.result = result;
    10         }
    11         public T call() {
    12             task.run();
    13             return result;
    14         }
    15     }
     

    由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。

    并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。因此FutureTask既是Future、

    Runnable,又是包装了Callable( 如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。


    简单示例

      1  package com.effective.java.concurrent.task;
      2 
      3 import java.util.concurrent.Callable;
      4 import java.util.concurrent.ExecutionException;
      5 import java.util.concurrent.ExecutorService;
      6 import java.util.concurrent.Executors;
      7 import java.util.concurrent.Future;
      8 import java.util.concurrent.FutureTask;
      9 
     10 /**
     11  * 
     12  * @author mrsimple
     13  *
     14  */
     15 public class RunnableFutureTask {
     16 
     17     /**
     18      * ExecutorService
     19      */
     20     static ExecutorService mExecutor = Executors.newSingleThreadExecutor();
     21 
     22     /**
     23      * 
     24      * @param args
     25      */
     26     public static void main(String[] args) {
     27         runnableDemo();
     28         futureDemo();
     29     }
     30 
     31     /**
     32      * runnable, 无返回值
     33      */
     34     static void runnableDemo() {
     35 
     36         new Thread(new Runnable() {
     37 
     38             @Override
     39             public void run() {
     40                 System.out.println("runnable demo : " + fibc(20));
     41             }
     42         }).start();
     43     }
     44 
     45     /**
     46      * 其中Runnable实现的是void run()方法,无返回值;Callable实现的是 V
     47      * call()方法,并且可以返回执行结果。其中Runnable可以提交给Thread来包装下
     48      * ,直接启动一个线程来执行,而Callable则一般都是提交给ExecuteService来执行。
     49      */
     50     static void futureDemo() {
     51         try {
     52             /**
     53              * 提交runnable则没有返回值, future没有数据
     54              */
     55             Future<?> result = mExecutor.submit(new Runnable() {
     56 
     57                 @Override
     58                 public void run() {
     59                     fibc(20);
     60                 }
     61             });
     62 
     63             System.out.println("future result from runnable : " + result.get());
     64 
     65             /**
     66              * 提交Callable, 有返回值, future中能够获取返回值
     67              */
     68             Future<Integer> result2 = mExecutor.submit(new Callable<Integer>() {
     69                 @Override
     70                 public Integer call() throws Exception {
     71                     return fibc(20);
     72                 }
     73             });
     74 
     75             System.out
     76                     .println("future result from callable : " + result2.get());
     77 
     78             /**
     79              * FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,
     80              * 另外它还可以包装Runnable(实际上会转换为Callable)和Callable
     81              * <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行
     82              * ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。
     83              */
     84             FutureTask<Integer> futureTask = new FutureTask<Integer>(
     85                     new Callable<Integer>() {
     86                         @Override
     87                         public Integer call() throws Exception {
     88                             return fibc(20);
     89                         }
     90                     });
     91             // 提交futureTask
     92             mExecutor.submit(futureTask) ;
     93             System.out.println("future result from futureTask : "
     94                     + futureTask.get());
     95 
     96         } catch (InterruptedException e) {
     97             e.printStackTrace();
     98         } catch (ExecutionException e) {
     99             e.printStackTrace();
    100         }
    101     }
    102 
    103     /**
    104      * 效率底下的斐波那契数列, 耗时的操作
    105      * 
    106      * @param num
    107      * @return
    108      */
    109     static int fibc(int num) {
    110         if (num == 0) {
    111             return 0;
    112         }
    113         if (num == 1) {
    114             return 1;
    115         }
    116         return fibc(num - 1) + fibc(num - 2);
    117     }
    118 
    119 }
     
  • 相关阅读:
    VMware下三种网络连接模式介绍
    Linux下tomcat的启动,关闭,以及shutdown失败杀死进程的方法
    C语言 寒假作业 01
    学期总结
    第十六周助教总结
    第十五周助教总结
    C语言I博客作业08
    first program
    第十四周助教总结
    前七章主要知识点
  • 原文地址:https://www.cnblogs.com/lintong/p/4371281.html
Copyright © 2011-2022 走看看