<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    letter Y A N. G Brass Letter F a n-spo D Pewter Uppercase Letter I N G
    隨筆 - 4, 文章 - 10, 評論 - 2, 引用 - 0
    數(shù)據(jù)加載中……

    實現(xiàn) Java 多線程并發(fā)控制框架

    所面臨的問題


    圖 1. 線程場景
    圖 1. 線程場景

    這幅圖中節(jié)點代表一個 single Thread,邊代表執(zhí)行的步驟。

    整幅圖代表的意思是,ROOT 線程執(zhí)行完畢后執(zhí)行 T1 線程,T1 執(zhí)行完畢后并發(fā)的執(zhí)行 T2 和 T3。而從 T2 和 T3 指向 T4 的兩條邊表示的是 T4 必須等 T2 和 T3 都執(zhí)行完畢以后才能開始執(zhí)行。剩下的步驟以此類推,直到 END 作為整個過程的結(jié)束。當(dāng)然,這只是個簡略的示意圖,可能面對的一個線程場景會有上百個線程。還有,你可以觀察到這整個場景只有一個入口點和一個出口點,這意味著什么?在下文中為你解釋。

    這其中涉及到了 Java 線程的同步互斥機制。例如如何讓 T1 在 T2 和 T3 之前運行,如何讓 T2 和 T3 都執(zhí)行完畢之后開啟 T4 線程。

    模型的描述

    如何來描述圖 1 中所示的場景呢?可以采用 XML 的格式來描述我們的模型。我定義一個“Thread” element 來表示線程。

    <ThreadList>
    <Thread ID = "thread-id" PRETHREAD = "prethread1, prethread2…"></Thread>
    <Thread ID = "thread-id" PRETHREAD = "prethread3, prethread4…"></Thread>
    </ThreadList>

    其中 ID 是線程的唯一標(biāo)識符,PRETHREAD 便是該線程的直接先決線程的ID,每個線程 ID 之間用逗號隔開。

    在 Thread 這個 element 里面可以加入你想要該線程執(zhí)行任務(wù)的具體信息。

    實際上模型的描述是解決問題非常重要的一個環(huán)節(jié),整個線程場景可以用一種一致的形式來描述,作為 Java 多線程并發(fā)控制框架引擎的輸入。也就是將線程運行的模式用 XML 來描述出來,這樣只用改動 XML 配置文件就可以更改整個線程運行的模式,不用改動任何的源代碼。

    兩種實現(xiàn)機制

    對于 Java 多線程的運行框架來說,我們將采用“外”和“內(nèi)”的兩種模式來實現(xiàn)。


    “外” - 主線程輪詢


    圖 2. 靜態(tài)類圖
    圖 2. 靜態(tài)類圖 

    Thread 是工作線程。ThreadEntry 是 Thread 的包裝類,prerequisite 是一個 HashMap,它含有 Thread 的先決線程的狀態(tài)。如圖1中顯示的那樣,T4 的先決線程是 T2 和 T3,那么 prerequisite 中就包含 T2 和 T3 的狀態(tài)。TestScenario 中的 threadEntryList 中包含所有的 ThreadEntry。


    圖 3. 線程執(zhí)行場景
    圖 3. 線程執(zhí)行場景 

    TestScenario 作為主線程,作為一個“外”在的監(jiān)控者,不斷地輪詢 threadEntryList 中所有 ThreadEntry 的狀態(tài),當(dāng) ThreadEntry 接受到 isReady 的查詢后查詢自己的 prerequisite,當(dāng)其中所有的先決線程的狀態(tài)為“正常結(jié)束時”,它便返回 ready,那么 TestScenario 便會調(diào)用 ThreadEntry 的 startThread() 方法授權(quán)該 ThreadEntry 運行線程,Thread 便通過 run() 方法來真正執(zhí)行線程。并在正常執(zhí)行完畢后調(diào)用 setPreRequisteState() 方法來更新整個 Scenario,threadEntryList 中所有 ThreadEntry 中 prerequisite 里面含有該 Thread 的狀態(tài)信息為“正常結(jié)束”。


    圖 4. 狀態(tài)更改的過程
    圖 4. 狀態(tài)更改的過程 

    如圖 1 中所示的 T4 的先決線程為 T2 和 T3,T2 和 T3 并行執(zhí)行。如圖 4 所示,假設(shè) T2 先執(zhí)行完畢,它會調(diào)用 setPreRequisteState() 方法來更新整個 Scenario, threadEntryList 中所有 ThreadEntry 中 prerequisite 里面含有該 T2 的狀態(tài)信息為“正常結(jié)束”。此時,T4 的 prerequisite 中 T2 的狀態(tài)為“正常結(jié)束”,但是 T3 還沒有執(zhí)行完畢,所以其狀態(tài)為“未完畢”。所以 T4 的 isReady 查詢返回為 false,T4 不會執(zhí)行。只有當(dāng) T3 執(zhí)行完畢后更新狀態(tài)為“正常結(jié)束”后,T4 的狀態(tài)才為 ready,T4 才會開始運行。

    其余的節(jié)點也以此類推,它們正常執(zhí)行完畢的時候會在整個的 scenario 中廣播該線程正常結(jié)束的信息,由主線程不斷地輪詢各個 ThreadEntry 的狀態(tài)來開啟各個線程。

    這便是采用主控線程輪詢狀態(tài)表的方式來控制 Java 多線程運行框架的實現(xiàn)方式之一。

    優(yōu)點:概念結(jié)構(gòu)清晰明了,實現(xiàn)簡單。避免采用 Java 的鎖機制,減少產(chǎn)生死鎖的幾率。當(dāng)發(fā)生異常導(dǎo)致其中某些線程不能正常執(zhí)行完畢的時候,不會產(chǎn)生掛起的線程。

    缺點:采用主線程輪詢機制,耗費 CPU 時間。當(dāng)圖中的節(jié)點太多的(n>??? 而線程單個線程執(zhí)行時間比較短的時候 t<??? 需要進(jìn)一步研究)時候會產(chǎn)生線程啟動的些微延遲,也就是說實時性能在極端情況下不好,當(dāng)然這可以另外寫一篇文章來專門探討。


    “內(nèi)” - wait&notify

    相對于“外”-主線程輪詢機制來說,“內(nèi)”采用的是自我控制連鎖觸發(fā)機制。


    圖 5. 鎖機制的靜態(tài)類圖
    圖 5. 鎖機制的靜態(tài)類圖 

    Thread 中的 lock 為當(dāng)前 Thread 的 lock,lockList 是一個 HashMap,持有其后繼線程的 lock 的引用,getLock 和 setLock 可以對 lockList 中的 Lock 進(jìn)行操作。其中很重要的一個成員是 waitForCount,這是一個引用計數(shù)。表明當(dāng)前線程正在等待的先決線程的個數(shù),例如圖 1 中所示的 T4,在初始的情況下,他等待的先決線程是 T2 和 T3,那么它的 waitForCount 等于 2。


    圖 6. 鎖機制執(zhí)行順序圖
    圖 6. 鎖機制執(zhí)行順序圖 

    當(dāng)整個過程開始運行的時候,我們將所有的線程 start,但是每個線程所持的 lock 都處于 wait 狀態(tài),線程都會處于 waiting 的狀態(tài)。此時,我們將 root thread 所持有的自身的 lock notify,這樣 root thread 就會運行起來。當(dāng) root 的 run 方法執(zhí)行完畢以后。它會檢查其后續(xù)線程的 waitForCount,并將其值減一。然后再次檢查 waitForCount,如果 waitForCount 等于 0,表示該后續(xù)線程的所有先決線程都已經(jīng)執(zhí)行完畢,此時我們 notify 該線程的 lock,該后續(xù)線程便可以從 waiting 的狀態(tài)轉(zhuǎn)換成為 running 的狀態(tài)。然后這個過程連鎖遞歸的進(jìn)行下去,整個過程便會執(zhí)行完畢。

    我們還是以 T2,T3,T4 為例,當(dāng)進(jìn)行 initThreadLock 過程的時候,我們可以知道 T4 有兩個直接先決線程 T2 和 T3,所以 T4 的 waitForCount 等于 2。我們假設(shè) T3 先執(zhí)行完畢,T2 仍然在 running 的狀態(tài),此時他會首先遍歷其所有的直接后繼線程,并將他們的 waitForCount 減去 1,此時他只有一個直接后繼線程 T4,于是 T4 的 waitForCount 減去 1 以后值變?yōu)?1,不等于 0,此時不會將 T4 的 lock notify,T4 繼續(xù) waiting。當(dāng) T2 執(zhí)行完畢之后,他會執(zhí)行與 T3 相同的步驟,此時 T4 的 waitForCount 等于 0,T2 便 notify T4 的 lock,于是 T4 從 waiting 狀態(tài)轉(zhuǎn)換成為 running 狀態(tài)。其他的節(jié)點也是相似的情況。

    當(dāng)然,我們也可以將整個過程的信息放在另外的一個全局對象中,所有的線程都去查找該全局對象來獲取各自所需的信息,而不是采取這種分布式存儲的方式。

    優(yōu)點:采用 wait&notify 機制而不采用輪詢的機制,不會浪費CPU資源。執(zhí)行效率較高。而且相對于“外”-主線程輪詢的機制來說實時性更好。

    缺點:采用 Java 線程 Object 的鎖機制,實現(xiàn)起來較為復(fù)雜。而且采取一種連鎖觸發(fā)的方式,如果其中某些線程異常,會導(dǎo)致所有其后繼線程的掛起而造成整個 scenario 的運行失敗。為了防止這種情況的發(fā)生,我們還必須建立一套線程監(jiān)控的機制來確保其正常運行。


    延伸

    下面的圖所要表達(dá)的是這樣一種遞歸迭代的概念。例如在圖1 中展示的那樣,T1 這個節(jié)點表示的是一個線程?,F(xiàn)在,忘掉線程這樣一個概念,將 T1 抽象為一個過程,想象它是一個銀河系,深入到 T1 中去,它也是一個許多子過程的集合,這些子過程之間的關(guān)系模式就如圖 1 所示那樣,可以用一個圖來表示。


    圖 7. 嵌套子過程
    圖 7. 嵌套子過程 

    可以想象一下這是怎樣的一個框架,具有無窮擴展性的過程框架,我們只用定義各個過程之間的關(guān)系,我們不用關(guān)心過程是怎樣運行的。事實上,可以在最終的節(jié)點上指定一個實際的工作,比如讀一個文件,或者submit一個JCL job,或者執(zhí)行一條sql statement。

    其實,按照某種遍歷規(guī)則,完全可以將這種嵌套遞歸的結(jié)構(gòu)轉(zhuǎn)化成為一個一層扁平結(jié)構(gòu)的圖,而不是原來的分層的網(wǎng)狀結(jié)構(gòu),但是我們不這樣做的原因是基于以下的幾點考慮:

    1. 如果這樣做,會導(dǎo)致圖節(jié)點太多,邊太多,令人眼花繚亂。
    2. 不這樣做更主要的原因是每一個場景,如圖 7 中的 T1,T13,是狀態(tài)聚集的一個單元,具有高復(fù)用性和可靠性。
    3. 框架是高度抽象的,它實際的執(zhí)行可以是分布式的,一個單元可以是一個系統(tǒng),作為和其他系統(tǒng)的分界標(biāo)志。

    實際上,這是一個狀態(tài)聚集的層次控制框架,我們可以依賴此框架來執(zhí)行自主運算。我們將在其它的文章中來討論它的應(yīng)用。



    總結(jié)

    本文介紹了一種 Java 多線程并發(fā)控制的框架,并給出了其兩種實現(xiàn)的模型,它們有各自的優(yōu)缺點,有各自的適用范圍。當(dāng)需要進(jìn)行 Java 線程的并發(fā)控制的時候,可以作為參考。



    參考資料



    關(guān)于作者

    陳威,華中科技大學(xué)碩士,IBM CSDL Software Engineer,所在的 Team 是 DB2 for z/OS。聯(lián)系方式:chenwbj@cn.ibm.com


     

     

    posted on 2008-10-02 23:12 rainman 閱讀(631) 評論(1)  編輯  收藏 所屬分類: java多線程

    評論

    # re: 實現(xiàn) Java 多線程并發(fā)控制框架  回復(fù)  更多評論   

    不知道您看懂了這篇文章了沒有?反正我是看不懂,不知道你能不能實現(xiàn)份代碼?如果能的話能話,能不能給我一份?謝謝啦 junmingabc@gmail.com
    2010-07-25 14:11 | 小陳
    主站蜘蛛池模板: 亚洲AV乱码一区二区三区林ゆな| 亚洲?V乱码久久精品蜜桃| 女人张开腿等男人桶免费视频| 成人免费视频试看120秒| 国产免费拔擦拔擦8x| 国产亚洲一区二区三区在线不卡| 国产亚洲婷婷香蕉久久精品 | 久久精品国产亚洲麻豆| 亚洲国产三级在线观看| 亚洲性色成人av天堂| 亚洲av成人无码网站…| 久久av免费天堂小草播放| 16女性下面扒开无遮挡免费| 成年美女黄网站色大免费视频| 亚洲AV无码成人精品区大在线| 国精无码欧精品亚洲一区| 亚洲人成免费电影| 黄色一级毛片免费| 毛片无码免费无码播放| 妞干网手机免费视频| 亚洲成A∨人片在线观看不卡| 精品亚洲国产成人| 国产免费久久精品99久久| 国产h肉在线视频免费观看| 成人伊人亚洲人综合网站222| 亚洲国产a∨无码中文777| 国产精品亚洲精品青青青| 精品人妻系列无码人妻免费视频 | 久久成人a毛片免费观看网站| 大地资源免费更新在线播放| 国产亚洲视频在线播放| 激情综合亚洲色婷婷五月| 色爽黄1000部免费软件下载| 亚洲三级在线免费观看| 亚洲国产日韩成人综合天堂| 亚洲日韩乱码中文无码蜜桃臀| 免费人成视频在线观看免费| 亚洲免费观看在线视频| 亚洲色偷偷狠狠综合网| 国产成人精品亚洲日本在线| 怡红院免费全部视频在线视频|