背景:对于客户端来说经常会有多线程的需求,一般为了线程安全会加锁,或者使用特殊的集合来处理,基本会满足我们的需求。但是有些多线程场景是在特殊环境下,服务端数据源一直发送处理数据到客户端,然后客户端处理逻辑比较复杂属于耗时操作,放在主线程会导致界面卡顿,因此会不断的用子线程来执行,并且对数据处理的执行顺序还必须是先进先出的模式,不然数据可能会出现问题。
需求:
- 接受到数据在子线程中进行处理,处理完数据返回主线程改变界面。
- 数据按照接收顺序执行,多个数据同时执行时在前面线程没有执行完成时后面的数据进行等待,一个一个按照先进先出的顺序进行执行。
根据需求首先考虑的就是阻塞队列BlockingQueue,经过一番对比选用LinkedBlockingQueue来进行实现。
LinkedBlockingQueue在安卓中的实现和在java中的实现不太一样,考虑到子线程处理主线程显示的逻辑,网上参考了比较多其他的博客,后面才有了下面的处理
1.首先创建LinkedBlockingQueue
private val linkedBlockingQueue = LinkedBlockingQueue<T>()
2.接受服务器push过来的数据,并且保存进LinkedBlockingQueue
linkedBlockingQueue.put(T)
3.在启动类的时候通过rxjava开启子线程获取LinkedBlockingQueue中排队的数据进行处理,处理完成后返回主线程进行操作
init {
addSubscribe(Flowable.interval(0, 500, TimeUnit.MILLISECONDS)
.flatMap {
//获取的方法poll,如果生产者没有数据,那么这里的消费者拿到的数据是为null,需要做判断
var T = linkedBlockingQueue.poll()
Flowable.just(update(T)) //处理逻辑
}
.compose(RxUtils.rxSchedulerHelper())//rxjava线程切换
.subscribe({
mView?.showView(data)
}, {}))
}
LinkedBlockingQueue的基本方法讲解:
LinkedBlockingQueue构造的时候若没有指定大小,则默认大小为Integer.MAX_VALUE,当然也可以在构造函数的参数中指定大小。LinkedBlockingQueue不接受null。
添加元素的方法有三个:add,put,offer。
add :方法在添加元素的时候,若超出了度列的长度会直接抛出异常:
put :方法,若向队尾添加元素的时候发现队列已经满了会发生阻塞一直等待空间,以加入元素。
offer :方法在添加元素时,如果发现队列已满无法添加的话,会直接返回false。从队列中取出并移除头元素的方法有:poll,remove,take。
poll :若队列为空,返回null。
remove :若队列为空,抛出NoSuchElementException异常。
take :若队列为空,发生阻塞,等待有元素。