Callable介面:
Callable,新啟執行緒的一種方式,返回結果並且可能丟擲異常的任務,在前面的新啟執行緒的文章中用過,但是沒有具體講解
優點:
可以獲取執行緒的執行結果,也稱為返回值
通過與Future的結合,可以實現利用Future來跟蹤非同步計算的結果
Runnable和Callable的區別:
Callable規定的方法是call(),Runnable規定的介面是run();
Callable的任務執行後可返回值,而Runnable的任務是不能有返回值的;
call方法可以丟擲異常,run方法不可以
執行Callable任務可以拿到一個Future物件,表示非同步計算的結果,它提供了檢查是否計算完成的方法,以等待計算的完成,並檢索計算的結果,通過Future物件可以瞭解任務執行情況,可以取消任務的執行,還可以獲取執行結果
Future介面:
Future是一個介面,代表了一個非同步計算的結果,介面中的方法用來檢查計算是否完成,等待完成和得到計算結果;
當計算完成後,只能通過get()方法得到結果,get()方法會阻塞,一直到執行緒的計算結果完成並返回;
如果想取消,那麼呼叫cancel()方法,其他方法用於確定任務是正常完成還是取消了;
一旦計算完成了,那麼這個計算就不能被取消
FutureTask類:
FutureTask類實現了RunnableFuture介面,而RunnableFuture介面是繼承了Runnable和Future介面,所以說FutureTask是一個提供非同步計算結果的任務;
FutureTask可以用來包裝Callable或者Runnable介面的實現物件,因為FutureTask實現了Runnable介面,所以FutureTask也可以提交給執行緒池
Callable,Future,FutureTask三者之間的關係:
Callable的兩種執行方式:
1:藉助FutureTask,包裝Callable介面的實現類,然後傳遞給Thread執行緒執行
package org.dance.day2.future; import org.dance.tools.SleepTools; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * Callable的兩種執行方式 * @author ZYGisComputer */ public class UseCallable { /** * 實現Callable介面的執行緒 */ private static class UseCall implements Callable<Integer>{ private int sum; @Override public Integer call() throws Exception { System.out.println("callable子執行緒開始執行任務計算"); Thread.sleep(2000); for (int i = 0; i < 5000; i++) { sum += i; } System.out.println("子執行緒任務計算完成,返回值:"+sum); return sum; } } public static void main(String[] args) throws ExecutionException, InterruptedException { UseCall useCall = new UseCall(); // 使用FutureTask包裝 FutureTask<Integer> futureTask = new FutureTask<>(useCall); // 包裝為Thread Thread thread = new Thread(futureTask); thread.start(); // 開始主執行緒的任務 Random random = new Random(); SleepTools.second(1); if(random.nextBoolean()){ System.out.println("獲取Callable result:"+futureTask.get()); }else{ System.out.println("中斷計算"); // 中斷計算,取消執行緒的執行 futureTask.cancel(true); } } }
2:藉助執行緒池來執行
UseCall useCall = new UseCall(); // 建立一個執行緒池 ExecutorService executorService = Executors.newCachedThreadPool(); Future<Integer> future = executorService.submit(useCall);
執行緒池這個只貼上關鍵程式碼,執行緒池的知識就不在這多說了,之後會具體講解
返回的Future介面的使用和FutureTask是一樣的
這個介面實現的執行緒,是有返回值的
可以說一下我之前用到的場景
是這樣的,我之前用到的一般是用於雲上,或者儲存伺服器下載電子檔案,就是本身我一個介面就是需要查詢資料庫並,進行結果的大量計算和結果轉換的,同時還要上雲上下載比較大的電子檔案,所以我採用Callable配合執行緒池來完成雲上檔案的下載;
作者:彼岸舞
時間:2020\10\04
內容關於:併發程式設計
本文來源於網路,只做技術分享,一概不負任何責任