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
内容關于:并發程式設計
本文來源于網絡,隻做技術分享,一概不負任何責任