中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

多線程中Future模式的詳細(xì)介紹

本篇內(nèi)容介紹了“多線程中Future模式的詳細(xì)介紹”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到榮縣網(wǎng)站設(shè)計(jì)與榮縣網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:做網(wǎng)站、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名與空間、雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋榮縣地區(qū)。

在高性能編程中,并發(fā)編程已經(jīng)成為了極為重要的一部分。在單核CPU性能已經(jīng)趨于極限時(shí),我們只能通過(guò)多核來(lái)進(jìn)一步提升系統(tǒng)的性能,因此就催生了并發(fā)編程。

由于并發(fā)編程比串行編程更困難,也更容易出錯(cuò),因此,我們就更需要借鑒一些前人優(yōu)秀的,成熟的設(shè)計(jì)模式,使得我們的設(shè)計(jì)更加健壯,更加完美。

而Future模式,正是其中使用最為廣泛,也是極為重要的一種設(shè)計(jì)模式。今天就跟阿丙了解一手Future模式!

生活中的Future模式

為了更快的了解Future模式,我們先來(lái)看一個(gè)生活中的例子。

場(chǎng)景1:

午飯時(shí)間到了,同學(xué)們要去吃飯了,小王下樓,走了20分鐘,來(lái)到了肯德基,點(diǎn)餐,排隊(duì),吃飯一共花了20分鐘,又花了20分鐘走回公司繼續(xù)工作,合計(jì)1小時(shí)。

場(chǎng)景2

午飯時(shí)間到了,同學(xué)們要去吃飯了,小王點(diǎn)了個(gè)肯德基外賣,很快,它就拿到了一個(gè)訂單(雖然訂單不能當(dāng)飯吃,但是有了訂單,還怕吃不上飯嘛)。接著小王可以繼續(xù)干活,30分鐘后,外賣到了,接著小王花了10分鐘吃飯,接著又可以繼續(xù)工作了,成功的卷到了隔壁的小汪。

多線程中Future模式的詳細(xì)介紹

很明顯,在這2個(gè)場(chǎng)景中,小王的工作時(shí)間更加緊湊,特別是那些排隊(duì)的時(shí)間都可以讓外賣員去干,因此可以更加專注于自己的本職工作。聰明的你應(yīng)該也已經(jīng)體會(huì)到了,場(chǎng)景1就是典型的函數(shù)同步調(diào)用,而場(chǎng)景2是典型的異步調(diào)用。

而場(chǎng)景2的異步調(diào)用,還有一個(gè)特點(diǎn),就是它擁有一個(gè)返回值,這個(gè)返回值就是我們的訂單。這個(gè)訂單很重要,憑借著這個(gè)訂單,我們才能夠取得當(dāng)前這個(gè)調(diào)用所對(duì)應(yīng)的結(jié)果。

這里的訂單就如同F(xiàn)uture模式中的Future,這是一個(gè)合約,一份承諾。雖然訂單不能吃,但是手握訂單,不怕沒(méi)吃的,雖然Future不是我們想要的結(jié)果,但是拿著Future就能在將來(lái)得到我們想要的結(jié)果。

因此,F(xiàn)uture模式很好的解決了那些需要返回值的異步調(diào)用。

Future模式中的主要角色

一個(gè)典型的Future模式由以下幾個(gè)部分組成:

  • Main:系統(tǒng)啟動(dòng),調(diào)用Client發(fā)出請(qǐng)求

  • Client:返回Data對(duì)象,立即返回FutureData,并開(kāi)啟ClientThread線程裝配RealData

  • Data:返回?cái)?shù)據(jù)的接口

  • FutureData:Future數(shù)據(jù),構(gòu)造很快,但是是一個(gè)虛擬的數(shù)據(jù),需要裝配RealData,好比一個(gè)訂單

  • RealData:真實(shí)數(shù)據(jù),其構(gòu)造是比較慢的,好比上面例子中的肯德基午餐。

它們之間的相互關(guān)系如下圖:

多線程中Future模式的詳細(xì)介紹

其中,值得注意是Data,RealData和FutureData。這是一組典型的代理模式,Data接口表示對(duì)外數(shù)據(jù),RealData表示真實(shí)的數(shù)據(jù),就好比午餐,獲得它的成本比較高,需要很多時(shí)間;相對(duì)的FutureData作為RealData的代理,類似于一個(gè)訂單/契約,通過(guò)FutureData,可以在將來(lái)獲得RealData。

因此,F(xiàn)uture模式本質(zhì)上是代理模式的一種實(shí)際應(yīng)用。

實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Future模式

根據(jù)上面的設(shè)計(jì),讓我們來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的代理模式吧!

首先是Data接口,代表數(shù)據(jù):

public interface Data {     public String getResult (); }

接著是FutureData,也是整個(gè)Future模式的核心:

public class FutureData implements Data {     // 內(nèi)部需要維護(hù)RealData     protected RealData realdata = null;               protected boolean isReady = false;     public synchronized void setRealData(RealData realdata) {         if (isReady) {              return;         }         this.realdata = realdata;         isReady = true;         //RealData已經(jīng)被注入,通知getResult()         notifyAll();                                    }     //會(huì)等待RealData構(gòu)造完成     public synchronized String getResult() {                  while (!isReady) {             try {                 //一直等待,直到RealData被注入                 wait();                                        } catch (InterruptedException e) {             }         }         //真正需要的數(shù)據(jù)從RealData獲取         return realdata.result;                           } }

下面是RealData:

public class RealData implements Data {     protected final String result;     public RealData(String para) {         StringBuffer sb=new StringBuffer();         //假設(shè)這里很慢很慢,構(gòu)造RealData不是一個(gè)容易的事         result =sb.toString();     }     public String getResult() {         return result;     } }

然后從Client得到Data:

public class Client {     //這是一個(gè)異步方法,返回的Data接口是一個(gè)Future     public Data request(final String queryStr) {         final FutureData future = new FutureData();         new Thread() {                                                   public void run() {                                      // RealData的構(gòu)建很慢,所以在單獨(dú)的線程中進(jìn)行                 RealData realdata = new RealData(queryStr);                 //setRealData()的時(shí)候會(huì)notify()等待在這個(gè)future上的對(duì)象                 future.setRealData(realdata);             }                                                        }.start();         // FutureData會(huì)被立即返回,不會(huì)等待RealData被構(gòu)造完         return future;                               } }

最后一個(gè)Main函數(shù),把所有一切都串起來(lái):

public static void main(String[] args) {     Client client = new Client();     //這里會(huì)立即返回,因?yàn)榈玫降氖荈utureData而不是RealData     Data data = client.request("name");     System.out.println("請(qǐng)求完畢");     try {         //這里可以用一個(gè)sleep代替了對(duì)其他業(yè)務(wù)邏輯的處理         //在處理這些業(yè)務(wù)邏輯的過(guò)程中,RealData被創(chuàng)建,從而充分利用了等待時(shí)間         Thread.sleep(2000);     } catch (InterruptedException e) {     }     //使用真實(shí)的數(shù)據(jù),如果到這里數(shù)據(jù)還沒(méi)有準(zhǔn)備好,getResult()會(huì)等待數(shù)據(jù)準(zhǔn)備完,再返回     System.out.println("數(shù)據(jù) = " + data.getResult()); }

這是一個(gè)最簡(jiǎn)單的Future模式的實(shí)現(xiàn),雖然簡(jiǎn)單,但是已經(jīng)包含了Future模式中最精髓的部分。對(duì)大家理解JDK內(nèi)部的Future對(duì)象,有著非常重要的作用。

Java中的Future模式

Future模式是如此常用,在JDK內(nèi)部已經(jīng)有了比較全面的實(shí)現(xiàn)和支持。下面,讓我們一起看看JDK內(nèi)部的Future實(shí)現(xiàn):

多線程中Future模式的詳細(xì)介紹

首先,JDK內(nèi)部有一個(gè)Future接口,這就是類似前面提到的訂單,當(dāng)然了,作為一個(gè)完整的商業(yè)化產(chǎn)品,這里的Future的功能更加豐富了,除了get()方法來(lái)獲得真實(shí)數(shù)據(jù)以外,還提供一組輔助方法,比如:

  • cancel():如果等太久,你可以直接取消這個(gè)任務(wù)

  • isCancelled():任務(wù)是不是已經(jīng)取消了

  • isDone():任務(wù)是不是已經(jīng)完成了

  • get():有2個(gè)get()方法,不帶參數(shù)的表示無(wú)窮等待,或者你可以只等待給定時(shí)間

下面代碼演示了這個(gè)Future的使用方法:

//異步操作 可以用一個(gè)線程池   ExecutorService executor = Executors.newFixedThreadPool(1);   //執(zhí)行FutureTask,相當(dāng)于上例中的 client.request("name") 發(fā)送請(qǐng)求   //在這里開(kāi)啟線程進(jìn)行RealData的call()執(zhí)行   Future<String> future = executor.submit(new RealData("name"));   System.out.println("請(qǐng)求完畢,數(shù)據(jù)準(zhǔn)備中");   try {       //這里依然可以做額外的數(shù)據(jù)操作,這里使用sleep代替其他業(yè)務(wù)邏輯的處理       Thread.sleep(2000);   } catch (InterruptedException e) {   }   //如果此時(shí)call()方法沒(méi)有執(zhí)行完成,則依然會(huì)等待   System.out.println("數(shù)據(jù) = " + future.get());

整個(gè)使用過(guò)程非常簡(jiǎn)單,下面我們來(lái)分析一下executor.submit()里面究竟發(fā)生了什么:

public <T> Future<T> submit(Callable<T> task) {     if (task == null) throw new NullPointerException();     // 根據(jù)Callable對(duì)象,創(chuàng)建一個(gè)RunnableFuture,這里其實(shí)就是FutureTask     RunnableFuture<T> ftask = newTaskFor(task);     //將ftask推送到線程池     //在新線程中執(zhí)行的,就是run()方法,在下面的代碼中有給出     execute(ftask);     //返回這個(gè)Future,將來(lái)通過(guò)這個(gè)Future就可以得到執(zhí)行的結(jié)果     return ftask; } protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {     return new FutureTask<T>(callable); }

最關(guān)鍵的部分在下面,F(xiàn)utureTask作為一個(gè)線程單獨(dú)執(zhí)行時(shí),會(huì)將結(jié)果保存到outcome中,并設(shè)置任務(wù)的狀態(tài),下面是FutureTask的run()方法:

多線程中Future模式的詳細(xì)介紹

從FutureTask中獲得結(jié)果的實(shí)現(xiàn)如下:

public V get() throws InterruptedException, ExecutionException {        int s = state;        //如果沒(méi)有完成,就等待,回到用park()方法阻塞線程        //同時(shí),所有等待線程會(huì)在FutureTask的waiters字段中排隊(duì)等待        if (s <= COMPLETING)            s = awaitDone(false, 0L);        return report(s);    }    private V report(int s) throws ExecutionException {        //outcome里保存的就是最終的計(jì)算結(jié)果        Object x = outcome;        if (s == NORMAL)            //正常完成,就返回outcome            return (V)x;        //如果沒(méi)有正常完成, 比如被用戶取消了,或者有異常了,就拋出異常        if (s >= CANCELLED)            throw new CancellationException();        throw new ExecutionException((Throwable)x);    }

Future模式的高階版本&mdash;&mdash; CompletableFuture

Future模式雖然好用,但也有一個(gè)問(wèn)題,那就是將任務(wù)提交給線程后,調(diào)用線程并不知道這個(gè)任務(wù)什么時(shí)候執(zhí)行完,如果執(zhí)行調(diào)用get()方法或者isDone()方法判斷,可能會(huì)進(jìn)行不必要的等待,那么系統(tǒng)的吞吐量很難提高。

為了解決這個(gè)問(wèn)題,JDK對(duì)Future模式又進(jìn)行了加強(qiáng),創(chuàng)建了一個(gè)CompletableFuture,它可以理解為Future模式的升級(jí)版本,它最大的作用是提供了一個(gè)回調(diào)機(jī)制,可以在任務(wù)完成后,自動(dòng)回調(diào)一些后續(xù)的處理,這樣,整個(gè)程序可以把“結(jié)果等待”完全給移除了。

下面來(lái)看一個(gè)簡(jiǎn)單的例子:

多線程中Future模式的詳細(xì)介紹

在這個(gè)例子中,首先以getPrice()為基礎(chǔ)創(chuàng)建一個(gè)異步調(diào)用,接著,使用thenAccept()方法,設(shè)置了一個(gè)后續(xù)的操作,也就是當(dāng)getPrice()執(zhí)行完成后的后續(xù)處理。

不難看到,CompletableFuture比一般的Future更具有實(shí)用性,因?yàn)樗梢栽贔uture執(zhí)行成功后,自動(dòng)回調(diào)進(jìn)行下一步的操作,因此整個(gè)程序不會(huì)有任何阻塞的地方(也就是說(shuō)你不用去到處等待Future的執(zhí)行,而是讓Future執(zhí)行成功后,自動(dòng)來(lái)告訴你)。

以上面的代碼為例,CompletableFuture之所有會(huì)有那么神奇的功能,完全得益于AsyncSupply類(由上述代碼中的supplyAsync()方法創(chuàng)建)。

AsyncSupply在執(zhí)行時(shí),如下所示:

public void run() {             CompletableFuture<T> d; Supplier<T> f;             if ((d = dep) != null && (f = fn) != null) {                 dep = null; fn = null;                 if (d.result == null) {                     try {                         //這里就是你要執(zhí)行的異步方法                         //結(jié)果會(huì)被保存下來(lái),放到d.result字段中                         d.completeValue(f.get());                     } catch (Throwable ex) {                         d.completeThrowable(ex);                     }                 }                 //執(zhí)行成功了,進(jìn)行后續(xù)處理,在這個(gè)后續(xù)處理中,就會(huì)調(diào)用thenAccept()中的消費(fèi)者                 //這里就相當(dāng)于Future完成后的通知                 d.postComplete();             }         }

繼續(xù)看d.postComplete(),這里會(huì)調(diào)用后續(xù)一系列操作

final void postComplete() {              //省略部分代碼,重點(diǎn)在tryFire()里              //在tryFire()里,真正觸發(fā)了后續(xù)的調(diào)用,也就是thenAccept()中的部分              f = (d = h.tryFire(NESTED)) == null ? this : d;          }      }  }

絮叨

今天,我們主要介紹Future模式,我們從一個(gè)最簡(jiǎn)單的Future模式開(kāi)始,逐步深入,先后介紹了JDK內(nèi)部的Future模式實(shí)現(xiàn),以及對(duì)Future模式的進(jìn)化版本CompletableFuture做了簡(jiǎn)單的介紹。對(duì)

于多線程開(kāi)發(fā)而言,F(xiàn)uture模式的應(yīng)用極其廣泛,可以說(shuō)這個(gè)模式已經(jīng)成為了異步開(kāi)發(fā)的基礎(chǔ)設(shè)施。

“多線程中Future模式的詳細(xì)介紹”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

分享名稱:多線程中Future模式的詳細(xì)介紹
文章源于:http://www.2m8n56k.cn/article20/jphcco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷推廣網(wǎng)站內(nèi)鏈網(wǎng)站改版品牌網(wǎng)站建設(shè)網(wǎng)站收錄用戶體驗(yàn)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:[email protected]。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)
主站蜘蛛池模板: 亚洲天堂视频网站 | 九九精品在线视频 | 久操免费在线视频 | 国产精品国产国产aⅴ | 美国一级毛片视频 | 欧美日韩在线观看一区 | 国内精品亚洲 | 欧美一级毛片久久精品 | 亚洲一区在线观看视频 | 国产日韩在线视频 | 国产精品黄在线观看免费 | 免费一级大毛片a一观看不卡 | 国产成人精品一区二三区2022 | 日韩精品一区二区三区高清 | 日韩永久在线观看免费视频 | 日韩精品免费视频 | 中国欧美一级毛片免费 | 欧美成人精品大片免费流量 | 国产亚洲精品午夜高清影院 | 亚洲欧美日韩中文字幕在线 | 久草在线视频资源 | 视频在线二区 | 国产精品久久久久久久hd | 色一欲一性一乱一区二区三区 | 亚洲成年网站在线观看 | 在线日本视频 | 99久久免费看精品国产一区 | 99久久99久久精品免费看子 | 美女视频网站免费播放视 | 亚洲手机看片 | 国产成人精品免费视频软件 | 日本高清视频免费在线观看 | 黄色三级网址 | 最新精品亚洲成a人在线观看 | 成人毛片免费观看视频在线 | 日韩精品永久免费播放平台 | 免费在线一级片 | 黄 色 成 年人网站 黄 色 免费网 站 成 人 | 嫩草一区二区三区四区乱码 | 国产精品亚洲天堂 | 中国黄色一级毛片 |