標籤:callable future futuretask java並發編程
建立線程:
1. 繼承Thread
2. 實現Runnable
仔細觀察會發現void run() ,這個方法沒有傳回值,也就無法獲得線程執行結果。
Callable
返回結果並且可能拋出異常的任務。實現者定義了一個不帶任何參數的叫做 call 的方法。
Callable 介面類似於 Runnable,兩者都是為那些其執行個體可能被另一個線程執行的類設計的。但是 Runnable 不會返回結果,並且無法拋出經過檢查的異常。
V call()
計算結果,如果無法計算結果,則拋出一個異常。
跟Runnable功能類似,用於建立線程,但是call方法有傳回值
V - call 方法的結果類型
Future
介面 Future<V>
V - 此 Future 的 get 方法所返回的結果類型
Future 表示非同步計算的結果。它提供了檢查計算是否完成的方法【isDone()】,以等待計算的完成,並擷取計算的結果【get()】。計算完成後只能使用 get 方法來擷取結果,如有必要,計算完成前可以阻塞此方法。取消則由 cancel 方法來執行。還提供了其他方法,以確定任務是正常完成還是被取消了【isCancelled() 】。一旦計算完成,就不能再取消計算。如果為了可取消性而使用 Future 但又不提供可用的結果,則可以聲明 Future<?> 形式類型、並返回 null 作為底層任務的結果。
FutureTask
實現了Future介面
類 FutureTask<V>
型別參數:
V - 此 FutureTask 的 get 方法所返回的結果類型。
可取消的非同步計算。利用開始和取消計算的方法、查詢計算是否完成的方法和擷取計算結果的方法,此類提供了對 Future 的基本實現。僅在計算完成時才能擷取結果;如果計算尚未完成,則阻塞 get 方法。一旦計算完成,就不能再重新開始或取消計算。
| 方法 |
意義 |
| FutureTask(Callable<V> callable) |
建立一個 FutureTask,一旦運行就執行給定的 Callable。 |
| FutureTask(Runnable runnable, V result) |
建立一個 FutureTask,一旦運行就執行給定的 Runnable,並安排成功完成時 get 返回給定的結果 。 |
| boolean cancel(boolean mayInterruptIfRunning) |
試圖取消對此任務的執行。 |
| protected void done() |
當此任務轉換到狀態 isDone(不管是正常地還是通過取消)時,調用受保護的方法。 |
| V get() |
如有必要,等待計算完成,然後擷取其結果。 |
| V get(long timeout, TimeUnit unit) |
如有必要,最多等待為使計算完成所給定的時間之後,擷取其結果(如果結果可用)。 |
| boolean isCancelled() |
如果在任務正常完成前將其取消,則返回 true。 |
| boolean isDone() |
如果任務已完成,則返回 true。 |
| void run() |
除非已將此 Future 取消,否則將其設定為其計算的結果。 |
| protected boolean runAndReset() |
執行計算而不設定其結果,然後將此 Future 重設為初始狀態,如果計算遇到異常或已取消,則該操作失敗。 |
| protected void set(V v) |
除非已經設定了此 Future 或已將其取消,否則將其結果設定為給定的值。 |
執行個體
我們可以這樣理解,FutureTask就是一個後台線程,它不同於一般的實現Runnable的線程,FutureTask封裝了資訊,並且會儲存結果。當我們對結果感興趣的任意時刻,可以直接調用get方法。
SwingWorker(實現了Future介面)其實就是一個很好的例子
一方面介面要相應使用者的滑鼠點擊事件,一方面需要去計算耗時的任務(比如計算素數)。如果將計算任務安排在主線程裡,就會造成介面的卡死,即相應不了使用者的點擊事件。因此可以借用SwingWork
public class TestFutureTask { public static void main(String[] args) throws Exception { System.out.println("Hello World!"); FutureTask futureTask = new FutureTask(new CalculateTask()); Thread task = new Thread(futureTask); task.start(); //監控計算任務是否結束 while(!futureTask.isDone()){ System.out.println("響應使用者其他的需求..."); //Thread.sleep(300); } //擷取結果,如果結果沒有準備好,則會阻塞在這裡 System.out.println(futureTask.get()); }}class CalculateTask implements Callable<List<Integer>>{ /* * 計算12321可以由那兩個素數相加得到 */ @Override public List<Integer> call() throws Exception{ List<Integer> list = new ArrayList<Integer>(); long start = System.currentTimeMillis(); int count = 0; for(int i = 2; i < 12321 ; i ++){ if(isPrime(i)){ count++; System.out.print(i + "\t"); if(count % 20 == 0){ System.out.println(); } } } System.out.println("\n共有素數:" + count); for(int i = 2; i <= 12321/2 ; i ++){ //System.out.println(i+","+(12321-i)); if(isPrime(i) && isPrime(12321 - i)){ list.add(i); list.add(12321 - i); } //Thread.sleep(500); } System.out.println("計算結果耗時:" + (System.currentTimeMillis() - start)+"ms"); return list; } public static boolean isPrime(int prime){ int num = (int)Math.sqrt(prime); for(int i = 2; i <= Math.sqrt(prime) ; i ++){ if(prime % i == 0){ return false; } } return true; }}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Java並發編程之Callable,Future,FutureTask