Callable接口:java
Callable,新啓線程的一種方式,返回結果而且可能拋出異常的任務,在前面的新啓線程的文章中用過,可是沒有具體講解數據庫
優勢:編程
能夠獲取線程的執行結果,也稱爲返回值服務器
經過與Future的結合,能夠實現利用Future來跟蹤異步計算的結果網絡
Runnable和Callable的區別:併發
Callable規定的方法是call(),Runnable規定的接口是run();dom
Callable的任務執行後可返回值,而Runnable的任務是不能有返回值的;異步
call方法能夠拋出異常,run方法不能夠ide
運行Callable任務能夠拿到一個Future對象,表示異步計算的結果,它提供了檢查是否計算完成的方法,以等待計算的完成,並檢索計算的結果,經過Future對象能夠了解任務執行狀況,能夠取消任務的執行,還能夠獲取執行結果spa
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
內容關於:併發編程
本文來源於網絡,只作技術分享,一律不負任何責任