java中FutureTask的使用
FutureTask簡介
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
更多教程請參考 flydean的博客