Future類存在於JDK的concurrent包中,主要用途是接收Java的異步線程計算返回的結果。
個人理解的使用場景大概如下:
有兩個任務A和B,A任務中僅僅需要使用B任務計算成果,有兩種方法實現:
- A和B在同一個線程中順序執行。即先執行B,得到返回結果之后再執行A。
- 開兩個線程,A和B並行執行。當A需要B的計算結果時如果B還沒有執行完,A既可以選擇阻塞等待B執行完,也可以先做其他的工作,過一段時間后再詢問一次B。
毫無疑問,如果B是一個耗時比較大的計算任務時,后者比前者的效率高了很多。
使用Java的Future對象的實現。
import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class FutureDemo { public static void main(String[] args) { ExecutorService threadPool = Executors.newCachedThreadPool(); Future<Integer> future = threadPool.submit(new Callable<Integer>() { public Integer call() throws Exception { Thread.sleep(3000); return new Random().nextInt(100); } }); doSomething(); try { System.out.println("is B done : " + future.isDone()); System.out.println("result of B : " + future.get()); System.out.println("is B done : " + future.isDone()); int result = future.get(); doSomethingWithB(result); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } System.exit(0); } private static void doSomethingWithB(int result) { // TODO Auto-generated method stub } private static void doSomething() { // TODO Auto-generated method stub } }
輸出結果:
is B done : false result of B : 25 is B done : true
Future對象使用get方法獲取線程的返回值,即call方法的返回值。
不帶參數的get方法是阻塞方法,只要線程為返回結果就會一直阻塞直到有結果為止。
可以使用isDone方法判斷線程是否結束。也可以使用帶參數的get方法,若指定時間內還沒有得到線程返回值,會拋出TimeoutException的異常。
該方法源碼:
/** * Waits if necessary for at most the given time for the computation * to complete, and then retrieves its result, if available. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return the computed result * @throws CancellationException if the computation was cancelled * @throws ExecutionException if the computation threw an * exception * @throws InterruptedException if the current thread was interrupted * while waiting * @throws TimeoutException if the wait timed out */ V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;