1. 程式人生 > >Callable,Future,FutureTask

Callable,Future,FutureTask

spa nds 查看 rate sub clas owa running ring

1.概念定義 2.實現例子 3.總結 1.概念定義 1.Callable Callable是一個接口,效果類似Runnable接口。實現該接口,然後,耗時操作在call()方法中執行。與Runnable接口不同的是,call方法需要返回執行的結果。 技術分享
public interface Callable<V>{
  V call() throws Exception;
}

public interface Runnable{
  void run();
}
View Code 2.Future A Future represents the result of an asynchronous(異步的) computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.
The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready. Cancellation is performed by the cancel method. Additional methods are provided to determine if the task completed normally or was cancelled. Once a computation has completed, the computation cannot be cancelled. If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task. Future是一個接口,實現這個接口的對象具備的特征,可以取消任務,獲取任務的結果,判斷任務的執行狀態。Future就是對具體的Callable任務或者Runnable任務執行取消,獲取結果,獲取當前狀態。 技術分享
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;
}
View Code 3.FutureTask A cancellable asynchronous computation. This class provides a base implementation of Future, with methods to start and cancel a computation, query to see if the computation is complete, and retrieve the result of the computation. The result can only be retrieved when the computation has completed; the get methods will block if the computation has not yet completed. Once the computation has completed, the computation cannot be restarted or cancelled (unless the computation is invoked using runAndReset()). A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask implements Runnable, a FutureTask can be submitted to an Executor for execution. In addition to serving as a standalone class, this class provides protected functionality that may be useful when creating customized task classes. FutureTask實現了Future接口,實現了Runnable接口。那麽,它就是一個Runnable對象,Future對象。它的run方法就是執行耗時的操作。 應用: 技術分享
//創建FutureTask對象,傳入Callable對象;Callable對象,耗時操作是放在call方法裏面的
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureTaskExample {
       
       public static void main(String[] args) {
             
             
             Callable<String> worker = new Callable<String>() {
                    
                    @Override
                    public String call() throws Exception {
                           // TODO Auto-generated method stub
                           System.out.println("do computation");
                           return "computation result";
                    }
             } ;
             
             
             FutureTask<String> future = new FutureTask<String>(worker) {
                    @Override
                    protected void  done() {
                           
                       System.out.println("Done task");     
                    }
             };
             
             new Thread(future) {
                    
                    @Override
                    public void run() {
                           future.run();
                    }
                    
             }.start();
             
             try {
                    System.out.println("computation:"+future.get());
             } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
             } catch (ExecutionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
             }
       }
}
View Code

調用FutureTask的run方法就觸發執行,可以查看FutureTask的源碼得到解釋:調用run,會導致調用sync.innerRun();而innerRun會調用傳入的Callable對象的call方法:

技術分享
public class FutureTask<V> implements RunnableFuture<V> {


    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        sync = new Sync(callable);
    }

.....
    // The following (duplicated) doc comment can be removed once
    //
    // 6270645: Javadoc comments should be inherited from most derived
    //          superinterface or superclass
    // is fixed.
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    public void run() {
        sync.innerRun();
    }

    /**
     * Synchronization control for FutureTask. Note that this must be
     * a non-static inner class in order to invoke the protected
     * <tt>done</tt> method. For clarity, all inner class support
     * methods are same as outer, prefixed with "inner".
     *
     * Uses AQS sync state to represent run status
     */
    private final class Sync extends AbstractQueuedSynchronizer {
    
           void innerRun() {
            if (!compareAndSetState(READY, RUNNING))
                return;

            runner = Thread.currentThread();
            if (getState() == RUNNING) { // recheck after setting thread
                V result;
                try {
                    result = callable.call();
                } catch (Throwable ex) {
                    setException(ex);
                    return;
                }
                set(result);
            } else {
                releaseShared(0); // cancel
            }
        }

    }

}
View Code

2.實現例子

技術分享
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureTaskExample {
       
       public static void main(String[] args) {
             
             
             Callable<String> worker = new Callable<String>() {
                    
                    @Override
                    public String call() throws Exception {
                           // TODO Auto-generated method stub
                           System.out.println("do computation");
                           return "computation result";
                    }
             } ;
             
             
             FutureTask<String> future = new FutureTask<String>(worker) {
                    @Override
                    protected void  done() {
                           
                       System.out.println("Done task");     
                    }
             };
             
             new Thread(future) {
                    
                    @Override
                    public void run() {
                           future.run();
                    }
                    
             }.start();
             
             try {
                    System.out.println("computation:"+future.get());
             } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
             } catch (ExecutionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
             }
       }
}
View Code

3.總結

1.FutureTask就是一個Runnable對象,也是一個Future對象。 2.使用FutureTask要使用Callable對象 3.最終的耗時操作,計算是在Callable對象的call方法中執行 4.使用FutureTask是為了獲得Future接口定義的特性,可以獲得一個任務的執行狀態,執行結果,可以取消任務的執行。這都是Runnable對象不具備的特性,Thread對象也不具備這些特性。

Callable,Future,FutureTask