背景:對于客戶端來說經(jīng)常會有多線程的需求,一般為了線程安全會加鎖驾窟,或者使用特殊的集合來處理庆猫,基本會滿足我們的需求。但是有些多線程場景是在特殊環(huán)境下绅络,服務端數(shù)據(jù)源一直發(fā)送處理數(shù)據(jù)到客戶端月培,然后客戶端處理邏輯比較復雜屬于耗時操作,放在主線程會導致界面卡頓恩急,因此會不斷的用子線程來執(zhí)行杉畜,并且對數(shù)據(jù)處理的執(zhí)行順序還必須是先進先出的模式,不然數(shù)據(jù)可能會出現(xiàn)問題衷恭。
需求:
- 接受到數(shù)據(jù)在子線程中進行處理此叠,處理完數(shù)據(jù)返回主線程改變界面。
- 數(shù)據(jù)按照接收順序執(zhí)行匾荆,多個數(shù)據(jù)同時執(zhí)行時在前面線程沒有執(zhí)行完成時后面的數(shù)據(jù)進行等待拌蜘,一個一個按照先進先出的順序進行執(zhí)行。
根據(jù)需求首先考慮的就是阻塞隊列BlockingQueue牙丽,經(jīng)過一番對比選用LinkedBlockingQueue來進行實現(xiàn)简卧。
LinkedBlockingQueue在安卓中的實現(xiàn)和在java中的實現(xiàn)不太一樣,考慮到子線程處理主線程顯示的邏輯烤芦,網(wǎng)上參考了比較多其他的博客举娩,后面才有了下面的處理
1.首先創(chuàng)建LinkedBlockingQueue
private val linkedBlockingQueue = LinkedBlockingQueue<T>()
2.接受服務器push過來的數(shù)據(jù),并且保存進LinkedBlockingQueue
linkedBlockingQueue.put(T)
3.在啟動類的時候通過rxjava開啟子線程獲取LinkedBlockingQueue中排隊的數(shù)據(jù)進行處理,處理完成后返回主線程進行操作
init {
addSubscribe(Flowable.interval(0, 500, TimeUnit.MILLISECONDS)
.flatMap {
//獲取的方法poll铜涉,如果生產(chǎn)者沒有數(shù)據(jù)智玻,那么這里的消費者拿到的數(shù)據(jù)是為null,需要做判斷
var T = linkedBlockingQueue.poll()
Flowable.just(update(T)) //處理邏輯
}
.compose(RxUtils.rxSchedulerHelper())//rxjava線程切換
.subscribe({
mView?.showView(data)
}, {}))
}
LinkedBlockingQueue的基本方法講解:
LinkedBlockingQueue構造的時候若沒有指定大小芙代,則默認大小為Integer.MAX_VALUE吊奢,當然也可以在構造函數(shù)的參數(shù)中指定大小。LinkedBlockingQueue不接受null纹烹。
添加元素的方法有三個:add页滚,put,offer铺呵。
add :方法在添加元素的時候裹驰,若超出了度列的長度會直接拋出異常:
put :方法,若向隊尾添加元素的時候發(fā)現(xiàn)隊列已經(jīng)滿了會發(fā)生阻塞一直等待空間片挂,以加入元素幻林。
offer :方法在添加元素時,如果發(fā)現(xiàn)隊列已滿無法添加的話音念,會直接返回false沪饺。從隊列中取出并移除頭元素的方法有:poll,remove症昏,take随闽。
poll :若隊列為空,返回null肝谭。
remove :若隊列為空掘宪,拋出NoSuchElementException異常。
take :若隊列為空攘烛,發(fā)生阻塞魏滚,等待有元素。