Callable和Future
概述
-
Callable和Future,它倆很有意思的,一個產生結果,一個拿到結果。
-
Future表示一個可能還沒有完成的異步任務的結果,針對這個結果可以添加Callback以便在任務執行成功或失敗后作出相應的操作。
-
Callable接口中只有一個call()方法,和Runnable相比,該方法有返回值並允許拋出異常
-
FutureTask是Runnable, Future接口的實現類。
-
RunnableFuture
- 這個接口同時繼承Future接口和Runnable接口,在成功執行run()方法后,可以通過Future訪問執行結果。這個接口都實現類是FutureTask,一個可取消的異步計算,這個類提供了Future的基本實現,后面我們的demo也是用這個類實現,它實現了啟動和取消一個計算,查詢這個計算是否已完成,恢復計算結果。計算的結果只能在計算已經完成的情況下恢復。如果計算沒有完成,get方法會阻塞,一旦計算完成,這個計算將不能被重啟和取消,除非調用runAndReset方法。
- FutureTask能用來包裝一個Callable或Runnable對象,因為它實現了Runnable接口,而且它能被傳遞到Executor進行執行。為了提供單例類,這個類在創建自定義的工作類時提供了protected構造函數。
-
Future的主要方法
- get()方法可以當任務結束后返回一個結果,如果調用時,工作還沒有結束,則會阻塞線程,直到任務執行完畢get(long timeout,TimeUnit unit)做多等待timeout的時間就會返回結果
- cancel(boolean mayInterruptIfRunning)方法可以用來停止一個任務,如果任務可以停止(通過mayInterruptIfRunning來進行判斷),則可以返回true,如果任務已經完成或者已經停止,或者這個任務無法停止,則會返回false.
- isDone()方法判斷當前方法是否完成
- isCancel()方法判斷當前方法是否取消
示例
- 普通線程模式
public class BumThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(1000*3);
System.out.println("包子准備完畢");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ColdDishThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("涼菜准備完畢");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
// 等涼菜 -- 必須要等待返回的結果,所以要調用join方法
Thread t1 = new ColdDishThread();
t1.start();
t1.join();
// 等包子 -- 必須要等待返回的結果,所以要調用join方法
Thread t2 = new BumThread();
t2.start();
t2.join();
long end = System.currentTimeMillis();
System.out.println("准備完畢時間:"+(end-start));
}
- Future模式
public static void main(String[] args) throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
// 等涼菜
Callable ca1 = new Callable(){
@Override
public String call() throws Exception {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "涼菜准備完畢";
}
};
FutureTask<String> ft1 = new FutureTask<String>(ca1);
new Thread(ft1).start();
// 等包子 -- 必須要等待返回的結果,所以要調用join方法
Callable ca2 = new Callable(){
@Override
public Object call() throws Exception {
try {
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "包子准備完畢";
}
};
FutureTask<String> ft2 = new FutureTask<String>(ca2);
new Thread(ft2).start();
System.out.println(ft1.get());
System.out.println(ft2.get());
long end = System.currentTimeMillis();
System.out.println("准備完畢時間:"+(end-start));
}