這篇文章將為大家詳細(xì)講解有關(guān)JAVA中怎么使用 Future類,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
10年積累的做網(wǎng)站、成都網(wǎng)站建設(shè)經(jīng)驗(yàn),可以快速應(yīng)對客戶對網(wǎng)站的新想法和需求。提供各種問題對應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識你,你也不認(rèn)識我。但先網(wǎng)站設(shè)計(jì)后付款的網(wǎng)站建設(shè)流程,更有城北免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
1. Future的應(yīng)用場景
在并發(fā)編程中,我們經(jīng)常用到非阻塞的模型,在之前的多線程的三種實(shí)現(xiàn)中,不管是繼承thread類還是實(shí)現(xiàn)runnable接口,都無法保證獲取到之前的執(zhí)行結(jié)果。通過實(shí)現(xiàn)Callback接口,并用Future可以來接收多線程的執(zhí)行結(jié)果。
Future表示一個(gè)可能還沒有完成的異步任務(wù)的結(jié)果,針對這個(gè)結(jié)果可以添加Callback以便在任務(wù)執(zhí)行成功或失敗后作出相應(yīng)的操作。
舉個(gè)例子:比如去吃早點(diǎn)時(shí),點(diǎn)了包子和涼菜,包子需要等3分鐘,涼菜只需1分鐘,如果是串行的一個(gè)執(zhí)行,在吃上早點(diǎn)的時(shí)候需要等待4分鐘,但是因?yàn)槟阍诘劝拥臅r(shí)候,可以同時(shí)準(zhǔn)備涼菜,所以在準(zhǔn)備涼菜的過程中,可以同時(shí)準(zhǔn)備包子,這樣只需要等待3分鐘。那Future這種模式就是后面這種執(zhí)行模式。
2. Future的類圖結(jié)構(gòu)
Future接口定義了主要的5個(gè)接口方法,有RunnableFuture和SchedualFuture繼承這個(gè)接口,以及CompleteFuture和ForkJoinTask繼承這個(gè)接口。
RunnableFuture
這個(gè)接口同時(shí)繼承Future接口和Runnable接口,在成功執(zhí)行run()方法后,可以通過Future訪問執(zhí)行結(jié)果。
這個(gè)接口都實(shí)現(xiàn)類是FutureTask,一個(gè)可取消的異步計(jì)算,這個(gè)類提供了Future的基本實(shí)現(xiàn),后面我們的demo也是用這個(gè)類實(shí)現(xiàn),它實(shí)現(xiàn)了啟動(dòng)和取消一個(gè)計(jì)算,查詢這個(gè)計(jì)算是否已完成,恢復(fù)計(jì)算結(jié)果。計(jì)算的結(jié)果只能在計(jì)算已經(jīng)完成的情況下恢復(fù)。
如果計(jì)算沒有完成,get方法會阻塞,一旦計(jì)算完成,這個(gè)計(jì)算將不能被重啟和取消,除非調(diào)用runAndReset方法。
FutureTask能用來包裝一個(gè)Callable或Runnable對象,因?yàn)樗鼘?shí)現(xiàn)了Runnable接口,而且它能被傳遞到Executor進(jìn)行執(zhí)行。為了提供單例類,這個(gè)類在創(chuàng)建自定義的工作類時(shí)提供了protected構(gòu)造函數(shù)。
SchedualFuture
這個(gè)接口表示一個(gè)延時(shí)的行為可以被取消。通常一個(gè)安排好的future是定時(shí)任務(wù)SchedualedExecutorService的結(jié)果
CompleteFuture
一個(gè)Future類是顯示的完成,而且能被用作一個(gè)完成等級,通過它的完成觸發(fā)支持的依賴函數(shù)和行為。當(dāng)兩個(gè)或多個(gè)線程要執(zhí)行完成或取消操作時(shí),只有一個(gè)能夠成功。
ForkJoinTask
基于任務(wù)的抽象類,可以通過ForkJoinPool來執(zhí)行。一個(gè)ForkJoinTask是類似于線程實(shí)體,但是相對于線程實(shí)體是輕量級的。大量的任務(wù)和子任務(wù)會被ForkJoinPool池中的真實(shí)線程掛起來,以某些使用限制為代價(jià)。
3. Future的主要方法
Future接口主要包括5個(gè)方法
get()方法可以當(dāng)任務(wù)結(jié)束后返回一個(gè)結(jié)果,如果調(diào)用時(shí),工作還沒有結(jié)束,則會阻塞線程,直到任務(wù)執(zhí)行完畢
get(long timeout,TimeUnit unit)做多等待timeout的時(shí)間就會返回結(jié)果
cancel(boolean mayInterruptIfRunning)方法可以用來停止一個(gè)任務(wù),如果任務(wù)可以停止(通過mayInterruptIfRunning來進(jìn)行判斷),則可以返回true,如果任務(wù)已經(jīng)完成或者已經(jīng)停止,或者這個(gè)任務(wù)無法停止,則會返回false.
isDone()方法判斷當(dāng)前方法是否完成
isCancel()方法判斷當(dāng)前方法是否取消
4. Future示例demo
需求場景:等早餐過程中,包子需要3秒,涼菜需要1秒,普通的多線程需要四秒才能完成。先等涼菜,再等包子,因?yàn)榈葲霾藭r(shí),普通多線程啟動(dòng)start()方法,執(zhí)行run()中具體方法時(shí),沒有返回結(jié)果,所以如果要等有返回結(jié)果,必須是要1秒結(jié)束后才知道結(jié)果。
普通多線程:
public class BumThread extends Thread{ @Override public void run() { try { Thread.sleep(1000*3); System.out.println("包子準(zhǔn)備完畢"); } catch (InterruptedException e) { e.printStackTrace(); } } } public class ColdDishThread extends Thread{ @Override public void run() { try { Thread.sleep(1000); System.out.println("涼菜準(zhǔn)備完畢"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); // 等涼菜 -- 必須要等待返回的結(jié)果,所以要調(diào)用join方法 Thread t1 = new ColdDishThread(); t1.start(); t1.join(); // 等包子 -- 必須要等待返回的結(jié)果,所以要調(diào)用join方法 Thread t2 = new BumThread(); t2.start(); t2.join(); long end = System.currentTimeMillis(); System.out.println("準(zhǔn)備完畢時(shí)間:"+(end-start)); }
采用Future模式:
public static void main(String[] args) throws InterruptedException, ExecutionException { long start = System.currentTimeMillis(); // 等涼菜 Callable ca1 = new Callable(){ @Override public String call() throws Exception { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "涼菜準(zhǔn)備完畢"; } }; FutureTaskft1 = new FutureTask (ca1); new Thread(ft1).start(); // 等包子 -- 必須要等待返回的結(jié)果,所以要調(diào)用join方法 Callable ca2 = new Callable(){ @Override public Object call() throws Exception { try { Thread.sleep(1000*3); } catch (InterruptedException e) { e.printStackTrace(); } return "包子準(zhǔn)備完畢"; } }; FutureTask ft2 = new FutureTask (ca2); new Thread(ft2).start(); System.out.println(ft1.get()); System.out.println(ft2.get()); long end = System.currentTimeMillis(); System.out.println("準(zhǔn)備完畢時(shí)間:"+(end-start));
關(guān)于JAVA中怎么使用 Future類就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。