當(dāng)前位置:首頁(yè) > IT技術(shù) > 其他 > 正文

FutureTask 使用詳解
2022-05-31 17:19:58

?

FutureTask?相關(guān)

https://zhuanlan.zhihu.com/p/377296488

?

?

概述

FutureTask?可取消的異步任務(wù),提供Future的基礎(chǔ)實(shí)現(xiàn),并實(shí)現(xiàn)了Runnable接口。FutureTask包含了取消與啟動(dòng)計(jì)算的方法,查詢計(jì)算是否完成以及檢索計(jì)算結(jié)果的方法。只有在計(jì)算完成才能檢索到結(jié)果,調(diào)用get()方法時(shí)如果任務(wù)還沒(méi)有完成將會(huì)阻塞調(diào)用線程至到任務(wù)完成。一旦計(jì)算完成就不能重新開(kāi)始與取消計(jì)算,但可以調(diào)用runAndReset()重置狀態(tài)后再重新計(jì)算。

類(lèi)圖

?

?

FutureTask實(shí)現(xiàn)了RunnableFuture接口,而RunnableFuture接口擴(kuò)展自Future?Runnable接口,在創(chuàng)建FutureTask時(shí)可以使用Callable接口的實(shí)例或者Lambda表達(dá)式,也可以使用Runnable的實(shí)例,但內(nèi)部還是會(huì)使用適配器模式轉(zhuǎn)換成Callable實(shí)例類(lèi)型。

創(chuàng)建第一個(gè)任務(wù)

使用Callable創(chuàng)建一個(gè)FutureTask實(shí)例:

FutureTask<Boolean> future = new FutureTask<>(new Callable<Boolean>() {
   @Override
   public Boolean call() throws Exception {
     return true;
   }
 });

通過(guò)new一個(gè)對(duì)象的方法可以直接創(chuàng)建一個(gè)FutureTask實(shí)例,如果直接調(diào)用run方法將直接在當(dāng)前線程中運(yùn)行,不會(huì)開(kāi)啟新線程。

使用ExecutorService或者線程可以讓FutureTask進(jìn)行托管進(jìn)行,示例如下:

//托管給線程池處理
Future<?> futureResult = Executors.newCachedThreadPool().submit(future);
//托管給單獨(dú)線程處理
new Thread(future).start();

因?yàn)?code>FutureTask繼承了Runnable接口,所以它可以通過(guò)new Thread()的方式進(jìn)行運(yùn)行,再由future變量來(lái)檢索結(jié)果值或者取消任務(wù)等操作,通過(guò)線程池托管的方式也可以適用。

取消任務(wù)

遇到特殊情況時(shí)需要對(duì)沒(méi)有運(yùn)行的或者已經(jīng)運(yùn)行的任務(wù)進(jìn)行取消操作,這時(shí)可以調(diào)用cancel()方法,取消方法有一個(gè)布爾類(lèi)型的參數(shù)mayInterruptIfRunning;當(dāng)值為ture時(shí)將嘗試中斷托管的線程(調(diào)用托管線程的interrupt嘗試中斷)。

取消任務(wù)使用的是線程的中斷操作,如果任務(wù)是可取消的,在任務(wù)中存在阻塞線程的地方需要加上InterruptedException的異常捕獲來(lái)處理中斷異?;蛘咴谌蝿?wù)可取消點(diǎn)使用Thread.currentThread().isInterrupted()方法來(lái)判斷任務(wù)是否已經(jīng)發(fā)送的中斷請(qǐng)求以正常取消任務(wù)。

檢索結(jié)果值

使用FutureTask的一個(gè)重要目的是為了能獲取到任務(wù)的結(jié)果值,使用Callable使用一個(gè)任務(wù)調(diào)用點(diǎn)時(shí)可以在任務(wù)中返回一個(gè)引用類(lèi)型。

FutureTask內(nèi)部使用outcome變量存儲(chǔ)Callable的結(jié)果,調(diào)用FutureTask.get()方法將檢索結(jié)果值,但get()方法也會(huì)阻塞調(diào)用線程直到任務(wù)執(zhí)行完成或者取消。

get()方法還可以通過(guò)設(shè)置超時(shí)時(shí)間來(lái)指定等待的時(shí)長(zhǎng),超過(guò)等待時(shí)間后將會(huì)拋出TimeoutException異常。

總結(jié)

使用FutureTask可以完成任務(wù)的取消、檢查結(jié)果值,這兩項(xiàng)也是FutureTask的特色,但FutureTask的底層還是托管給Thread完成;相對(duì)于Thread檢查結(jié)果值會(huì)更新的方便,不再需要管理線程執(zhí)行的狀態(tài)與值。

在使用cancel方法需要注意任務(wù)是否可以取消,在任務(wù)內(nèi)部需要使用Thread.currentThread().isInterrupted()檢查中斷狀態(tài)并在Thread.sleep()?condition.wait()?Thread.join()?Thread.wait()使用線程進(jìn)行阻塞以及可中斷的I/O操作方法中捕獲InterruptedException異常以避免不必要的情況發(fā)生,在大多數(shù)任務(wù)中是不應(yīng)該被中斷的,所以最好在可中斷的任務(wù)中設(shè)置好檢查點(diǎn);在任務(wù)線程會(huì)被阻塞點(diǎn)捕獲InterruptedException異常,根據(jù)情況判斷是否需要取消任務(wù)。

?

?

?

?

本文摘自 :https://www.cnblogs.com/

開(kāi)通會(huì)員,享受整站包年服務(wù)立即開(kāi)通 >