阻塞队列是jdk1.5新特性,本质就是一个队列,当队列为空时,消费方阻塞等待,直到队列有新的对象;队列满了时,生产方阻塞等待,直到队列有空位时;它实现了多线程的排队等待。
队列,Queue接口,有先进先出的特性,与List,Set在同一级别,都继承了Collection接口,而BlockingQueue继承了Queue。
Queue提供了以下方法:
add,offer:add如果队列满了, 则抛出异常IIIegaISlabEepeplian,offer如果满则返回false
remove,poll:移除一个元素,为空时,remove抛异常NoSuchElementException,poll返回null,可以配合queue的size作循环
BlockingQueue提供了以下方法
put:类似add方法,但队列满了不抛异常,直接等待。
take:类似poll方法,队列空时不返回null,直接阻塞等待。
Blocking队列分为4种
LinkedBlockingQueue
的容量是没有上限的(说的不准确,在不指定时容量为Integer.MAX_VALUE,不要然的话在put时怎么会受阻呢),但是也可以选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。
ArrayBlockingQueue
在构造时需要指定容量,并可以选择是否需要公平性,如果公平参数被设置
true,等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来达到这种公平性的:即等待时间最长的线程会先操
作)。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。它是基于数组的阻塞循环队列,此队列按
FIFO(先进先出)原则对元素进行排序
PriorityBlockingQueue
是一个带优先级的队列,而不是先进先出队列。元素按优先级顺序被移除,该
队列也没有上限(看了一下源码,PriorityBlockingQueue是对PriorityQueue的再次包装,是基于堆数据结构的,而
PriorityQueue是没有容量限制的,与ArrayList一样,所以在优先阻塞队列上put时是不会受阻的。虽然此队列逻辑上是无界的,但是由
于资源被耗尽,所以试图执行添加操作可能会导致
OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外,往入该队列中的元
素要具有比较能力。
DelayQueue
(基于PriorityQueue来实现的)是一个存放Delayed
元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed
元素。如果延迟都还没有期满,则队列没有头部,并且poll将返回null。当一个元素的
getDelay(TimeUnit.NANOSECONDS)
方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不允许使用 null 元素。 下面是延迟接口:
使用阻塞队列两个显著的好处就是:多线程操作共同的队列时不需要额外的同步,另外就是队列会自动平衡负载,即那边(生产与消费两边)处理快了就会被阻塞掉,从而减少两边的处理速度差距
。
最后copy了一段代码示例
-
public
class
BlockingQueueTest {
-
public
static
void
main(String[] args) {
-
Scanner in = new
Scanner(System.in);
-
System.out.print("Enter base directory (e.g. /usr/local/jdk5.0/src): "
);
-
String directory = in.nextLine();
-
System.out.print("Enter keyword (e.g. volatile): "
);
-
String keyword = in.nextLine();
-
-
final
int
FILE_QUEUE_SIZE =
10
;
-
final
int
SEARCH_THREADS =
100
;
-
-
-
BlockingQueue<File> queue = new
ArrayBlockingQueue<File>(
-
FILE_QUEUE_SIZE);
-
-
-
FileEnumerationTask enumerator = new
FileEnumerationTask(queue,
-
new
File(directory));
-
new
Thread(enumerator).start();
-
-
-
for
(
int
i =
1
; i <= SEARCH_THREADS; i++)
-
new
Thread(
new
SearchTask(queue, keyword)).start();
-
}
-
}
-
class
FileEnumerationTask
implements
Runnable {
-
-
public
static
File DUMMY =
new
File(
""
);
-
-
private
BlockingQueue<File> queue;
-
private
File startingDirectory;
-
-
public
FileEnumerationTask(BlockingQueue<File> queue, File startingDirectory) {
-
this
.queue = queue;
-
this
.startingDirectory = startingDirectory;
-
}
-
-
public
void
run() {
-
try
{
-
enumerate(startingDirectory);
-
queue.put(DUMMY);
-
} catch
(InterruptedException e) {
-
}
-
}
-
-
-
public
void
enumerate(File directory)
throws
InterruptedException {
-
File[] files = directory.listFiles();
-
for
(File file : files) {
-
if
(file.isDirectory())
-
enumerate(file);
-
else
-
-
queue.put(file);
-
}
-
}
-
}
-
class
SearchTask
implements
Runnable {
-
private
BlockingQueue<File> queue;
-
private
String keyword;
-
-
public
SearchTask(BlockingQueue<File> queue, String keyword) {
-
this
.queue = queue;
-
this
.keyword = keyword;
-
}
-
-
public
void
run() {
-
try
{
-
boolean
done =
false
;
-
while
(!done) {
-
-
File file = queue.take();
-
if
(file == FileEnumerationTask.DUMMY) {
-
-
queue.put(file);
-
done = true
;
-
} else
-
search(file);
-
}
-
} catch
(IOException e) {
-
e.printStackTrace();
-
} catch
(InterruptedException e) {
-
}
-
}
-
public
void
search(File file)
throws
IOException {
-
Scanner in = new
Scanner(
new
FileInputStream(file));
-
int
lineNumber =
0
;
-
while
(in.hasNextLine()) {
-
lineNumber++;
-
String line = in.nextLine();
-
if
(line.contains(keyword))
-
System.out.printf("%s:%d:%s%n"
, file.getPath(), lineNumber,
-
line);
-
}
-
in.close();
-
}
-
}
分享到:
相关推荐
支持多线程的阻塞队列,使用模板技术,可存储任意类型数据
java中,常用的阻塞式队列Demo。包含:ArrayBlockingQueue、LinkedQueue、PriorityBlockingQueue
实现java模拟阻塞队列的例子,该代码包括,阻塞队列实现生产者,消费者。和模拟阻塞队列实现生产者及消费者模式,帮助你更好的理解java多线程
Java实现简单的阻塞队列2种方式,1使用wait(),notify();2使用countdownlatch实现
讲述线程池原理,线程池使用场景和注意事项,手动创建线程池方法,注意事项,阻塞队列的相关知识
14-阻塞队列BlockingQueue实战及其原理分析二.pdf
并发-线程池和阻塞队列 并发-线程池和阻塞队列 并发-线程池和阻塞队列
我们来讨论另外一类容器:阻塞队列。 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue、LinkedList(LinkedList是双向链表,它实现了Dequeue接口)。 使用非阻塞队列的时候有一个很大问题是:它不会对...
阻塞队列详解
c_c++阻塞队列的代码
主要介绍了剖析Java中阻塞队列的实现原理及应用场景,这里也对阻塞和非阻塞队列的不同之处进行了对比,需要的朋友可以参考下
并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue用法
基于Android操作系统上开发的一款软件,成功模拟了多个程序的创建、执行、阻塞等状态,模拟了执行队列、阻塞队列、就绪队列 - 运行中有什么问题可以私聊博主,本人高级安卓工程师,主页置顶有常见爆红解决的方法 ##...
c++11 实现的阻塞队列
day19_阻塞队列、线程池、File类、递归.pdf
阻塞队列是多线程中常用的数据结构,对于实现多线程之间的数据交换、同步等有很大作用。 阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。简而言之,阻塞队列...
10、阻塞队列BlockingQueue实战及其原理分析_
java阻塞队列(Blocking Queue)是一个支持两个附加操作的队列.txt
Java并发编程(21)并发新特性—阻塞队列和阻塞栈(含代码)编程开发技术共8页.pdf.zip
java阻塞队列实现原理及实例解析.docx