2.4.1 例子countDownLatch歌殃、CyclicBarrier

原始對賬系統(tǒng)拾弃,單線程

while(存在未對賬訂單){

????? pos = getPOrders();???// 查詢未對賬訂單

? ????dos = getDOrders();? ?? // 查詢派送單

? ????diff = check(pos, dos);? ?? // 執(zhí)行對賬操作

? ????save(diff);? ?? // 差異寫入差異庫

}

改為多線程:join

while(存在未對賬訂單){

? // 查詢未對賬訂單

? Thread T1 = new Thread(()->{

? ? pos = getPOrders();

? });

? T1.start();

? // 查詢派送單

? Thread T2 = new Thread(()->{

? ? dos = getDOrders();

? });

? T2.start();

? // 等待T1顽腾、T2結(jié)束

? T1.join();

? T2.join();

? diff = check(pos, dos);? ?// 執(zhí)行對賬操作

? save(diff);? ??// 差異寫入差異庫

}

創(chuàng)建線程耗時,用線程池優(yōu)化:?CountDownLatch?

Executor executor =Executors.newFixedThreadPool(2);??// 創(chuàng)建2個線程的線程池

while(存在未對賬訂單){

? CountDownLatch latch =new CountDownLatch(2);???// 計數(shù)器初始化為2

? // 查詢未對賬訂單

? executor.execute(()-> {

? ? pos = getPOrders();

? ? latch.countDown();

? });

? // 查詢派送單

? executor.execute(()-> {

? ? dos = getDOrders();

? ? latch.countDown();

? });

? latch.await();??// 等待兩個查詢操作結(jié)束

? diff = check(pos, dos);???// 執(zhí)行對賬操作

? save(diff);??? // 差異寫入差異庫

}

前面我們將 getPOrders() 和 getDOrders() 這兩個查詢操作并行了丑慎,但這兩個查詢操作和對賬操作 check()迟螺、save() 之間還是串行的拔妥。很顯然赶掖,這兩個查詢操作和對賬操作也是可以并行的,也就是說七扰,在執(zhí)行對賬操作的時候奢赂,可以同時去執(zhí)行下一輪的查詢操作,這個過程可以形象化地表述為下面這幅示意圖颈走。

那接下來我們再來思考一下如何實現(xiàn)這步優(yōu)化膳灶,兩次查詢操作能夠和對賬操作并行,對賬操作還依賴查詢操作的結(jié)果立由,這明顯有點生產(chǎn)者 - 消費者的意思轧钓,兩次查詢操作是生產(chǎn)者,對賬操作是消費者锐膜。既然是生產(chǎn)者 - 消費者模型毕箍,那就需要有個隊列,來保存生產(chǎn)者生產(chǎn)的數(shù)據(jù)道盏,而消費者則從這個隊列消費數(shù)據(jù)而柑。不過針對對賬這個項目,我設計了兩個隊列荷逞,并且兩個隊列的元素之間還有對應關系媒咳。具體如下圖所示,訂單查詢操作將訂單查詢結(jié)果插入訂單隊列种远,派送單查詢操作將派送單插入派送單隊列涩澡,這兩個隊列的元素之間是有一一對應的關系的。兩個隊列的好處是坠敷,對賬操作可以每次從訂單隊列出一個元素妙同,從派送單隊列出一個元素,然后對這兩個元素執(zhí)行對賬操作膝迎,這樣數(shù)據(jù)一定不會亂掉渐溶。

下面再來看如何用雙隊列來實現(xiàn)完全的并行。一個最直接的想法是:一個線程 T1 執(zhí)行訂單的查詢工作弄抬,一個線程 T2 執(zhí)行派送單的查詢工作茎辐,當線程 T1 和 T2 都各自生產(chǎn)完 1 條數(shù)據(jù)的時候,通知線程 T3 執(zhí)行對賬操作。這個想法雖看上去簡單拖陆,但其實還隱藏著一個條件弛槐,那就是線程 T1 和線程 T2 的工作要步調(diào)一致,不能一個跑得太快依啰,一個跑得太慢乎串,只有這樣才能做到各自生產(chǎn)完 1 條數(shù)據(jù)的時候,通知線程 T3速警。下面這幅圖形象地描述了上面的意圖:線程 T1 和線程 T2 只有都生產(chǎn)完 1 條數(shù)據(jù)的時候叹誉,才能一起向下執(zhí)行,也就是說闷旧,線程 T1 和線程 T2 要互相等待长豁,步調(diào)要一致;同時當線程 T1 和 T2 都生產(chǎn)完一條數(shù)據(jù)的時候忙灼,還要能夠通知線程 T3 執(zhí)行對賬操作匠襟。

Vector<P> pos;? ?// 訂單隊列

Vector<D> dos;? ?// 派送單隊列

Executor executor = Executors.newFixedThreadPool(1);??// 執(zhí)行回調(diào)的線程池

final CyclicBarrier barrier = new CyclicBarrier(2, ()->{

? ????? executor.execute(()->check());? ? ?//等到barrier.await()減為0才執(zhí)行

? });


void check(){

? P p = pos.remove(0);

? D d = dos.remove(0);

? diff = check(p, d);? ?// 執(zhí)行對賬操作

? save(diff);??? // 差異寫入差異庫

}


void checkAll(){

? // 循環(huán)查詢訂單庫

? Thread T1 = new Thread(()->{

? ? while(存在未對賬訂單){

? ? ????? pos.add(getPOrders());??? ? ? // 查詢訂單庫

? ? ? ????barrier.await();??? ? ? // 等待

? ? }

? });

? T1.start();?

? // 循環(huán)查詢運單庫

? Thread T2 = new Thread(()->{

? ? while(存在未對賬訂單){

? ? ????? dos.add(getDOrders());???// 查詢運單庫

? ? ? ????barrier.await();??? ? ? // 等待

? ? }

? });

? T2.start();

}

1.為啥要用線程池,而不是在回調(diào)函數(shù)中直接調(diào)用该园?

2.線程池為啥使用單線程的酸舍?

我的考慮:

1.使用線程池是為了異步操作,否則回掉函數(shù)是同步調(diào)用的里初,也就是本次對賬操作執(zhí)行完才能進行下一輪的檢查啃勉。

2.線程數(shù)量固定為1,防止了多線程并發(fā)導致的數(shù)據(jù)不一致双妨,因為訂單和派送單是兩個隊列璧亮,只有單線程去兩個隊列中取消息才不會出現(xiàn)消息不匹配的問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末斥难,一起剝皮案震驚了整個濱河市枝嘶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哑诊,老刑警劉巖群扶,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異镀裤,居然都是意外死亡竞阐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門暑劝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來骆莹,“玉大人,你說我怎么就攤上這事担猛∧豢眩” “怎么了丢氢?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長先改。 經(jīng)常有香客問我疚察,道長,這世上最難降的妖魔是什么仇奶? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任貌嫡,我火速辦了婚禮,結(jié)果婚禮上该溯,老公的妹妹穿的比我還像新娘岛抄。我一直安慰自己,他們只是感情好狈茉,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布夫椭。 她就那樣靜靜地躺著,像睡著了一般论皆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猾漫,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天点晴,我揣著相機與錄音,去河邊找鬼悯周。 笑死粒督,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的禽翼。 我是一名探鬼主播屠橄,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闰挡!你這毒婦竟也來了锐墙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤长酗,失蹤者是張志新(化名)和其女友劉穎溪北,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夺脾,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡之拨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了咧叭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚀乔。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖菲茬,靈堂內(nèi)的尸體忽然破棺而出吉挣,到底是詐尸還是另有隱情派撕,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布听想,位于F島的核電站腥刹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏汉买。R本人自食惡果不足惜衔峰,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛙粘。 院中可真熱鬧垫卤,春花似錦、人聲如沸出牧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舔痕。三九已至评抚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伯复,已是汗流浹背慨代。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留啸如,地道東北人侍匙。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像叮雳,于是被迫代替她去往敵國和親想暗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容