阻塞队列和生产者-消费者模式
阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法,如果队列已经满了,那么put方法将阻塞直到有可用空间。
如果队列为空,那么take方法将会阻塞直到有元素可用。队列可以是有界的也可以是无界的。
BlockingQueue简化了生产者-消费者设计的实现过程。它支持任意数量的生产者和消费者。一种常见的shenchanzhe-消费者模式就是线程池与工作队列的组合。在Executor任务执行框架中就体现了这种模式。
在类库中包含了Blockingqueue的多种实现。其中linkedBlockingQueue和ArrayBlockingQueue是FIFO队列。二者分别与linkedList和ArrayList类似。PriorityBlockingQueue是一种按优先级排序的队列,当你希望按某种顺序而不是FIFO处理元素时,这个队列非常有用。
最后一个Blockingqueue实现是SynchronousQueue,它没有存储功能,因此take和put会一直阻塞,直到另外一个线程已经准备好参与交付过程中。
public class ProducerConsumer {
static class FileCrawler implements Runnable {
private final BlockingQueue<File> fileQueue;
private final FileFilter fileFilter;
private final File root;
public FileCrawler(BlockingQueue<File> fileQueue,
final FileFilter fileFilter,
File root) {
this.fileQueue = fileQueue;
this.root = root;
this.fileFilter = new FileFilter() {
public boolean accept(File f) {
return f.isDirectory() || fileFilter.accept(f);
}
};
}
private boolean alreadyIndexed(File f) {
return false;
}
public void run() {
try {
crawl(root);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void crawl(File root) throws InterruptedException {
File[] entries = root.listFiles(fileFilter);
if (entries != null) {
for (File entry : entries)
if (entry.isDirectory())
crawl(entry);
else if (!alreadyIndexed(entry))
fileQueue.put(entry);
}
}
}
static class Indexer implements Runnable {
private final BlockingQueue<File> queue;
public Indexer(BlockingQueue<File> queue) {
this.queue = queue;
}
public void run() {
try {
while (true)
indexFile(queue.take());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public void indexFile(File file) {
// Index the file...
};
}
private static final int BOUND = 10;
private static final int N_CONSUMERS = Runtime.getRuntime().availableProcessors();
public static void startIndexing(File[] roots) {
BlockingQueue<File> queue = new LinkedBlockingQueue<File>(BOUND);
FileFilter filter = new FileFilter() {
public boolean accept(File file) {
return true;
}
};
for (File root : roots)
new Thread(new FileCrawler(queue, filter, root)).start();
for (int i = 0; i < N_CONSUMERS; i++)
new Thread(new Indexer(queue)).start();
}
}
本文介绍阻塞队列及其在生产者-消费者模式中的应用,包括不同类型的阻塞队列如LinkedBlockingQueue、ArrayBlockingQueue等,并通过一个文件爬取与索引的示例说明其实现。
41万+

被折叠的 条评论
为什么被折叠?



