2。2 Java BlockingQueue
在Java多线程编程中,如何能够实现高效安全的数据同步,是每个程序员都会面临的问题[10]。为了解决这个难题,Java给我们提供了BlockingQueue。BlockingQueue是阻塞队列的意思,它是Java提供一个接口,该接口的实现类都是线程安全的。通过该接口的实现类,我们可以轻松便捷地编写多线程的程序,无需考虑锁和同步问题。因为这些问题设计者们都已经替我们考虑好了,所以我们可以把更多的精力投入到业务本身中去。
BlockingQueue代表着阻塞队列,队列是一种特殊的线性表,一般只能在某一端进行数据的插入或取出[11]。如果我们想要安全地把数据从一个线程传输给另外一个线程的话,那么队列这种数据机构是一个不错的选择。BlockingQueue的作用如图2。2所示:
图2。2 队列示意图
从图2。2我们可知,队列可以暂存数据。数据可以从队列的一端进入,然后再从队列的一端取出。有两种常见的队列,它们分别为先进先出队列,和先进后出队列,先进后出队列一般称之为栈。它们的特点是都受限于在某端进行数据的插入和取出。来*自-优=尔,论:文+网www.youerw.com
先进先出:先进入队列的元素先出来,这样可以保证公平性。它限制在表的一端进行插入和删除运算,具有排队的功能[12]。
后进先出:后进入队列的元素先出来,公平性正好相反。最近进入队列的任务被优先地处理。
在多线程的环境中,要实现数据间的共享,我们就可以采用队列的形式来存储数据。例如在“生产者”和“消费者”问题中,就使用了队列作为数据交换的媒介。比如我们有10个生产者和10个消费者线程,如果我们想要把生产者产生的数据传递给消费者的话,就可以使用队列。生产者线程先生成数据,然后把数据送入到队列中,同时消费者线程从队列中取走数据。先生产的数据被消费者先取走,后生产的数据被消费者后取走,同时生产者和消费者并没有直接进行数据的交互,避免了一些同步问题。然而,生产者线程产生数据的速度和消费者线程提取数据的速度并不总是一样的,我们无法有效地控制它们的速度。如果消费者线程提取数据的速度大于生产者线程产生数据的速度,那么当队列内的数据为空时,就需要暂停消费者进程[13]。反之,则要暂停生产者的进程。在多线程的环境下,这会给我们的编程带来很大的难度。因为我们不仅要考虑到这些情况,还要兼顾着效率和安全。幸好在这个时候,Java的BlockingQueue出现了,它给我们的多线程编程带来了极大的便利。如图2。3和图2。4所示,BlockingQueue有如下常见的场景