在JAVA的多線程機制中,Runnable接口可以用來封裝一個異步運作的任務,但是它相當于是一個沒有參數類型和傳回
值的異步方法,是以在JAVA中就又出現了callable機制,callable是一個參數化的類型接口,裡面隻有一個call方法,但是該方法是
有傳回值的,而且傳回值類型就是參數類型。與callable接口相配套使用的就是Future接口,其作用就是用來儲存異步運算的結果和
和啟動一個異步運算,Future接口中一共有五個方法,分别用來查詢和控制線程運作的狀态和結構。
Future接口中的方法清單:
public interface Future<V>
{
V get() throws ....;//用來傳回運算的最後結果,如果計算還未完成,則會被阻塞
/*
*如果計算完成,則傳回true
*如果計算完成之前,調用這個方法逾時,則會發生TimeoutException異常。
*如果運作時線程被中斷則會發生InterruptedException中斷異常
*否則被阻塞
*/
V get(long timeout,TimeUnit unit) throws...;
/*
* 取消運算,mayInterrupt為true時中斷線程,但此時如果線程已經被阻塞或者休眠則會發生InterruptedException中斷異常
*/
void cancle(boolean mayInterrupt);
boolean isCancleed();//判斷線程是否被取消
boolean isDone();//判斷計算是否已經完成
}
但是在實際的運用中間我們還有更簡潔的機制那就是FutureTask包裝器,它可将Callable轉換成Future和Runnable,它同時是實作了兩者的接口的。
具體的使用方法如下面的代碼:
/**
* 定義一個任務類,實作Callable接口
*/
public static class MyCallableClass implements Callable<String>{
private int value = 0;
public MyCallableClass(int flag){
this.value = flag;
}
public String call() throws Exception{
if (this.value == 0){
// 如果value的值為0,則立即傳回
return "value = 0";
}
} else {
// value不為0,則抛出異常
throw new Exception("Invalid value!");
}
}
}
//開啟線程
case R.id.button3:
MyCallableClass task1 = new MyCallableClass(0);
FutureTask<String> Futask = new FutureTask<String>(task1);
Thread t = new Thread(Futask);
t.start();
try{
System.out.println("task1: " + Futask.get());
}
catch(Exception e)
{
System.out.println(e.toString());
}
break;
線程結束後,最後的結果将會輸出“alue=0”。這樣也就簡單的實作了将一個線程裡運算結果最後傳回的效果,其實這個功能說更簡單一點也就是利用Future
的特性實作了在主線程和子線程的通信問題,在主線程中可以得到子線程的最後結果,和控制、判斷子線程的運作狀态,不過這種通信效果僅僅隻是單向的,并不完美。
如果要實作線程間的完美通信,那就要用到一個更複雜的線程間的通信機制了,嗯,等下幾次再詳細的寫這個線程通信問題吧。