1. 程式人生 > 程式設計 >Java FutureTask類使用案例解析

Java FutureTask類使用案例解析

FutureTask一個可取消的非同步計算,FutureTask 實現了Future的基本方法,提空 start cancel 操作,可以查詢計算是否已經完成,並且可以獲取計算的結果。結果只可以在計算完成之後獲取,get方法會阻塞當計算沒有完成的時候,一旦計算已經完成,那麼計算就不能再次啟動或是取消。

一個FutureTask 可以用來包裝一個 Callable 或是一個runnable物件。因為FurtureTask實現了Runnable方法,所以一個 FutureTask可以提交(submit)給一個Excutor執行(excution).

FutureTask是java 5引入的一個類,從名字可以看出來FutureTask既是一個Future,又是一個Task。

我們看下FutureTask的定義:

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

FutureTask實現了RunnableFuture介面,RunnableFuture介面是Runnable和Future的綜合體。

作為一個Future,FutureTask可以執行非同步計算,可以檢視非同步程式是否執行完畢,並且可以開始和取消程式,並取得程式最終的執行結果。

除此之外,FutureTask還提供了一個runAndReset()的方法, 該方法可以執行task並且重置Future的狀態。

Callable和Runnable的轉換
我們知道Callable是有返回值的,而Runnable是沒有返回值的。
Executors提供了很多有用的方法,將Runnable轉換為Callable:

  public static <T> Callable<T> callable(Runnable task,T result) {
    if (task == null)
      throw new NullPointerException();
    return new RunnableAdapter<T>(task,result);
  }

FutureTask內部包含一個Callable,並且可以接受Callable和Runnable作為建構函式:

  public FutureTask(Callable<V> callable) {
    if (callable == null)
      throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;    // ensure visibility of callable
  }
  public FutureTask(Runnable runnable,V result) {
    this.callable = Executors.callable(runnable,result);
    this.state = NEW;    // ensure visibility of callable
  }

它的內部就是呼叫了Executors.callable(runnable,result);方法進行轉換的。

以Runnable執行

既然是一個Runnable,那麼FutureTask就可以以執行緒的方式執行,我們來看一個例子:

@Test
  public void convertRunnableToCallable() throws ExecutionException,InterruptedException {
    FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
      @Override
      public Integer call() throws Exception {
        log.info("inside callable future task ...");
        return 0;
      }
    });

    Thread thread= new Thread(futureTask);
    thread.start();
    log.info(futureTask.get().toString());
  }

上面例子是以單個執行緒來執行的,同樣我們也可以將FutureTask提交給執行緒池來執行:

  @Test
  public void workWithExecutorService() throws ExecutionException,InterruptedException {
    FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
      @Override
      public Integer call() throws Exception {
        log.info("inside futureTask");
        return 1;
      }
    });
    ExecutorService executor = Executors.newCachedThreadPool();
    executor.submit(futureTask);
    executor.shutdown();
    log.info(futureTask.get().toString());
  }

本文的例子可參考https://github.com/ddean2009/learn-java-concurrency/tree/master/futureTask

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。