常用的Thread類在run方法執行完之后是沒有返回值的,要實現子線程完成任務后返回值給主線程需要借助第三方轉存。Callable接口則提供了一種有返回值的多線程實現方法。下面以一個簡單的地主、監工和長工的例子展示這種接口的用法。
長工類:
長工類實現了Callable接口,線程運行完成后返回一個Integer值。
import java.util.concurrent.Callable;
public class Changgong implements Callable<Integer>{
private int hours=12;
private int amount;
@Override
public Integer call() throws Exception {
while(hours>0){
System.out.println("I'm working......");
amount ++;
hours--;
Thread.sleep(1000);
}
return amount;
}
}
public class Changgong implements Callable<Integer>{
private int hours=12;
private int amount;
@Override
public Integer call() throws Exception {
while(hours>0){
System.out.println("I'm working......");
amount ++;
hours--;
Thread.sleep(1000);
}
return amount;
}
}
地主:主進程
監工:FutureTask
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Dizhu {
public static void main(String args[]){
Changgong worker = new Changgong();
FutureTask<Integer> jiangong = new FutureTask<Integer>(worker);
new Thread(jiangong).start();
while(!jiangong.isDone()){
try {
System.out.println("看長工做完了沒...");
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int amount;
try {
amount = jiangong.get();
System.out.println("工作做完了,上交了"+amount);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
import java.util.concurrent.FutureTask;
public class Dizhu {
public static void main(String args[]){
Changgong worker = new Changgong();
FutureTask<Integer> jiangong = new FutureTask<Integer>(worker);
new Thread(jiangong).start();
while(!jiangong.isDone()){
try {
System.out.println("看長工做完了沒...");
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int amount;
try {
amount = jiangong.get();
System.out.println("工作做完了,上交了"+amount);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
運行結果:
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
工作做完了,上交了12
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
I'm working......
看工人做完了沒...
工作做完了,上交了12
從上面的例子可以看出,FutureTask 扮演了一個監工的角色,地主(主進程)通過不斷地詢問監工(isDone()方法)可以得知長工的工作是否完成,並且在長工完成工作后讓監工收取成果(get()方法)。