小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

聊聊多線程那一些事兒(task)之 二 延續(xù)操作

 行者花雕 2020-04-25

  hello,又見面啦,昨天我們簡單的介紹了如何去創(chuàng)建和運(yùn)行一個task、如何實(shí)現(xiàn)task的同步執(zhí)行、如何阻塞等待task集合的執(zhí)行完畢等待,昨天講的是task的最基本的知識點(diǎn),如果你沒有看昨天的博客,也不要急,你可以點(diǎn)擊下面的地址, 聊聊多線程哪一些事兒(task)之 一),先看看后,在回到這兒來繼續(xù)交流學(xué)習(xí)今天的文章,謝謝!

    今天主要和大家交流分享的是:task的延續(xù)操作、task的異步取消、異步方法等知識點(diǎn),希望通過本篇文章,能夠給你帶來一點(diǎn)點(diǎn)幫助我就高興的不要不要的啦。當(dāng)然啦,既然是交流,如果我有什么說的不對,或者說的不好的地方,大家多多指點(diǎn),多多包涵,如果能夠得到大牛的指點(diǎn),我也會高興的合不攏嘴,謝謝。好了,不廢話了,言歸正傳,繼續(xù)今天的分享加交流。

Task延續(xù)操作之WhenAny、WhenAll、ContinueWith

    上一篇文章我們已經(jīng)知道可以通過task.wait/task.WaitAny/task.WaitAll,等方法來實(shí)現(xiàn)等待一個tsak或者一組task的執(zhí)行完畢,這一個方法都會阻塞主線程(如果沒有看一篇文章的請單擊查看:聊聊多線程哪一些事兒(task)之 一),也就是這一些操作都是主流程的一個必然環(huán)節(jié),但是我們在實(shí)際項(xiàng)目中,也還會遇到這樣的場景,那就是主流程根本不關(guān)心task的執(zhí)行結(jié)果,但是task執(zhí)行完畢后,需要執(zhí)行一個其他的子業(yè)務(wù),那么這個時候WhenAny、WhenAll、ContinueWith就派上用場了,這幾個方法也就專門是為這樣的場景而存在的。哈哈,說了這么多,是不是覺得有點(diǎn)抽象,有點(diǎn)云里霧里的感覺,說實(shí)話,我自己都覺得說的太空洞,還不如來一個實(shí)際的場景+代碼實(shí)例,這樣整的更明白。

    實(shí)際業(yè)務(wù)場景:我想了半天,到得用什么樣的業(yè)務(wù)場景比較合適呢,最終決定還是以昨天酒店客房數(shù)據(jù)查詢?yōu)槔M(jìn)行為例。用戶在線預(yù)訂酒店時,由于真正的客房預(yù)訂是需要實(shí)時的到第三接口平臺預(yù)訂,所以用戶在自己系統(tǒng)下單后,并不代表真正的酒店預(yù)訂成功,真正的酒店預(yù)訂成功,是需要通過接口到第三方系統(tǒng)下單成功才算真正的預(yù)訂成功,并且一個平臺對接的接口都會有多個,平臺最終會比價后,選擇一個平臺利用最大化的接口下單。這樣以來,系統(tǒng)不可能讓用戶等待到第三方接口下單成功后,在返回的用戶吧,這樣用戶是沒有那么好的心情的來等待的,并且這樣也很容易超時的,所以在實(shí)際項(xiàng)目處理上,是需要將本系統(tǒng)下單和第三接口預(yù)訂兩個步驟解耦,實(shí)現(xiàn)異步預(yù)訂,其大致的業(yè)務(wù)邏輯是這樣的。

    第一步:用戶在系統(tǒng)發(fā)起酒店預(yù)訂請求

    第二步:本系統(tǒng)下單成功,并返回給用戶

    第三步:開啟一個異步線程,到接口方下單

    異步線程的處理邏輯大概是:

        其一:具有該客房的接口方各開啟一個異步線程

       其二:每一個線程的具體邏輯是,根據(jù)客房信息查詢具體的客房信息(客房狀態(tài)、價格、服務(wù)等)

        其三:當(dāng)每一個異步線程都執(zhí)行完畢后,對獲取到接口數(shù)據(jù)進(jìn)行對比分析,選擇一個最優(yōu)的接口方進(jìn)行預(yù)訂

        其四:預(yù)訂成功后,并發(fā)送一個消息給客戶

    好了,下面用一個簡單的實(shí)例代碼來模擬上面的處理邏輯和流程

/// <summary>/// 酒店在線預(yù)訂操作/// </summary>/// <param name="hotelBookInfo">用戶預(yù)訂的酒店信息</param>/// <returns>預(yù)訂結(jié)果</returns>private static object HotelBook(object hotelBookInfo)
{
    Console.WriteLine("用戶發(fā)起了酒店預(yù)訂請求!");
    Console.WriteLine("");// 第一步:首先本系統(tǒng)落地酒店預(yù)訂相關(guān)操作(數(shù)據(jù)校驗(yàn)、數(shù)據(jù)落地、日志記錄等等)// ---此處省略具體的業(yè)務(wù)邏輯代碼,根據(jù)業(yè)務(wù)需要自由發(fā)揮// 第二步:根據(jù)具有該客房的酒店接口商,開啟異步線程預(yù)訂酒店//(假設(shè)第一步操作都成功的,并且 攜程和藝龍都有該客房)// 模擬存儲獲取到的酒店客房數(shù)據(jù)集合List<string> listHotelRoomInfro = new List<string>();// 其一、通過傳統(tǒng)的 new 方式來實(shí)例化一個task對象,獲取 攜程 的客房時時數(shù)據(jù)Task newCtripTask = new Task(() =>{// 具體獲取業(yè)務(wù)邏輯處理...Thread.Sleep(new Random().Next(100, 1000));
        Console.WriteLine("攜程 接口數(shù)據(jù)獲取完畢!");
        Console.WriteLine("");
        listHotelRoomInfro.Add("我是來自 攜程 的最新客房信息,該客房可預(yù)訂,預(yù)訂價格為:100元");
    });// 啟動 tsak    newCtripTask.Start();// 其二、通過工廠 factory 來生成一個task對象,并自啟動:獲取 藝龍 的客房數(shù)據(jù)Task factoryElongTask = Task.Factory.StartNew(() =>{// 具體獲取業(yè)務(wù)邏輯處理...Thread.Sleep(new Random().Next(100, 1000));
        Console.WriteLine("藝龍 接口數(shù)據(jù)獲取完畢!");
        Console.WriteLine("");
        listHotelRoomInfro.Add("我是來自 藝龍 的最新客房信息,該客房可預(yù)訂,預(yù)訂價格為:99元");
    });// 其三:通過 Task.WhenAll() 來執(zhí)行 攜程和藝龍的客房數(shù)據(jù)獲取結(jié)果的后續(xù)處理 // Task.WhenAll() 可以用 Task.Factory.ContinueWhenAll()來代替,兩種的效果是一樣的 Task.Factory.ContinueWhenAll(new Task[] { newCtripTask, factoryElongTask }, (t) => { });
    Task.WhenAll(newCtripTask, factoryElongTask).ContinueWith((t) =>{
        Console.WriteLine("所有接口數(shù)據(jù)獲取完畢,現(xiàn)在進(jìn)行最優(yōu)選擇!");
        Console.WriteLine("");// 對比 所有接口獲取的實(shí)時數(shù)據(jù),找到一個平臺利益最大化的接口預(yù)訂// 具體的規(guī)則,每個平臺都有自己的規(guī)則,在此我們簡單的以價格最低為準(zhǔn),具體的對比邏輯就不在寫了// 根據(jù)數(shù)據(jù)分析,最終藝龍的價格最低,所以直接預(yù)訂藝龍的數(shù)據(jù)Console.WriteLine("藝龍接口最優(yōu),現(xiàn)在調(diào)用藝龍?jiān)诰€預(yù)訂接口!");
        Console.WriteLine("");// 模擬調(diào)用藝龍的酒店預(yù)訂接口,進(jìn)行酒店預(yù)訂Thread.Sleep(new Random().Next(100, 1000));// 預(yù)訂成功后,系統(tǒng)數(shù)據(jù)落地的相關(guān)業(yè)務(wù)操作.....Console.WriteLine("藝龍?jiān)诰€預(yù)訂成功,開始后續(xù)業(yè)務(wù)流程處理!");
    });// 第三步步:返回用戶,下單成功Console.WriteLine("您好,你的酒店下單成功,具體的預(yù)訂結(jié)果等待第三方酒店提高商的返回結(jié)果為準(zhǔn)!謝謝");
    Console.WriteLine("");return "構(gòu)建下單成功相關(guān)信息";
}
 

執(zhí)行結(jié)果:

通過上面的執(zhí)行結(jié)果,我們可以得出以下幾點(diǎn):

    其一、WhenAll里面的邏輯是在所有tsak都執(zhí)行完畢后,在執(zhí)行

    其二、whenAll的執(zhí)行,不會影響主線程的執(zhí)行

    其三、其實(shí)簡單的理解,WhenAll可以理解為一個task組的異步回調(diào)

    好了,詳細(xì)的舉例說了whenAll的使用,至于 WhenAny 使用就不在詳細(xì)說明了,其實(shí)從字面意思都能夠看明白啦,就是只要所有的task集合中,只有有一個task執(zhí)行完成,就在執(zhí)行whenAny里面的邏輯,也就是說,wenAll和whenAny的唯一區(qū)別就是:前者是要所有task都執(zhí)行完畢才執(zhí)行,后者只需要有一個執(zhí)行完畢就執(zhí)行里面的邏輯。

    其實(shí)WhenAny 的有實(shí)際應(yīng)用場景也是很多的,比如,一個具有競爭的業(yè)務(wù)邏輯中,最終只選擇一個效率對快的一個,那么WhenAny就能夠發(fā)揮其作用了。

    Task.WhenAll與Task.Factory.ContinueWhenAll

    Task.WhenAny 與Task.Factory.ContinueWhenAny

    這兩者是一個成對的等效操作,其實(shí)你閱讀兩個的底層源碼實(shí)現(xiàn),你會發(fā)現(xiàn),其實(shí)最終第底層實(shí)現(xiàn)都是調(diào)用的TaskFactory中的同一方法實(shí)現(xiàn),所以就不在啰嗦的寫一次Task.Factory.ContinueWhenAll的場景應(yīng)用,需要閱讀的底層源碼的,可以查看下面地址進(jìn)行閱讀:https://blog.csdn.net/weixin_33701294/article/details/85958795

    好了,今天就寫到這兒了,我仔細(xì)看了一下,文章篇幅已經(jīng)夠多了,本篇文章就不在介紹 task的異步取消、異步方法這兩個知識點(diǎn)了,明天我會在單獨(dú)一篇文章專門來介紹這兩個知識點(diǎn),想繼續(xù)看明天的后續(xù)文章的小伙伴們,點(diǎn)關(guān)注哦,明天一定補(bǔ)上,謝謝!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多