概述
從Java 5開始,Java就提供了Callable接口,可以把它看作是Runnable接口的增強版:Callable接口提供了一個call()方法作爲線程執行體,它可以有返回值,並且可以拋異常。但是如何獲取call()方法的返回值呢?
Java 5提供了Future接口來代表call()方法的返回值,併爲Future接口提供了FutureTask實現類,該類實現了Callable接口和Runnable接口。Future接口中定義了幾個公共方法來控制它關聯的Callable任務:
- boolean cancel(boolean):試圖取消該Future關聯的Callable任務。
- V get():返回call()方法的返回值。該方法將導致程序阻塞,必須等到子線程結束後纔得到返回值。
- V get(long timeout, TimeUnit unit):返回call()方法的返回值。該方法最多阻塞timeout和unit指定的時間,如果超過指定時間沒有返回,將會拋出TimeoutException。
- boolean isCancelled():如果在Callable任務正常結束前被取消,則返回true。
- boolean isDone():如果Callable任務已經完成,則返回true。
代碼示例
創建並啓動Callable線程的步驟如下:
(1)創建Callable接口實現類,並實現call()方法;
(2)創建Callable實現類的實例,並用FutureTask來包裝Callable對象,該FutureTask對象封裝了call()方法的返回值;
(3)使用FutureTask對象座位Thread的target創建並啓動線程;
(4)調用FutureTask對象的get()方法來獲得call()方法的返回值。
注意,Callable接口有泛型限制,Callable接口中的泛型形參類型必須與call()方法返回值類型相同。
package Demo;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
//Callable接口的泛型形參類型與call方法返回值類型一致
public class Demo implements Callable<Integer> {
@Override
public Integer call() {
int i = 0;
for (; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " i的值:" + i);
}
return i;
}
public static void main(String[] args) {
// 創建Callable對象
Demo dm = new Demo();
// 使用FutureTask包裝Callable對象
FutureTask<Integer> task = new FutureTask<>(dm);
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " i的值:" + i);
if (i == 20) {
new Thread(task, "有返回值的線程").start();
}
}
try {
System.out.println("子線程執行結束,i的值:" + task.get());
} catch (Exception e) {
e.printStackTrace();
}
}
}
主程序中當 i 的值等於20時,就會啓動Callable子線程,此時主線程和子線程併發執行。最後程序通過FutureTask對象的get()方法來獲取call()方法的返回值——該方法會導致主線程阻塞,直到call()方法執行結束。如果將try中的語句移到if語句塊中,會發現當 i 等於20時,等到子線程打印完畢後,主線程繼續從21開始打印。讀者可以自己嘗試。下面是本例的測試結果:
<pre name="code" class="html">main i的值:0
main i的值:1
......
main i的值:24
有返回值的線程 i的值:0
main i的值:25
有返回值的線程 i的值:1
main i的值:26
有返回值的線程 i的值:2
main i的值:27
有返回值的線程 i的值:3
main i的值:28
有返回值的線程 i的值:4
main i的值:29
有返回值的線程 i的值:5
main i的值:30
......
main i的值:92
有返回值的線程 i的值:36
main i的值:93
有返回值的線程 i的值:37
main i的值:94
有返回值的線程 i的值:38
main i的值:95
有返回值的線程 i的值:39
main i的值:96
有返回值的線程 i的值:40
main i的值:97
有返回值的線程 i的值:41
main i的值:98
有返回值的線程 i的值:42
main i的值:99
有返回值的線程 i的值:43
......
有返回值的線程 i的值:99
子線程執行結束,i的值:100