原文地址:http://www.blogjava.net/fidodido/archive/2005/10/11/15269.html
引子:
大家上过操作系统的都知道“生产者-消费者(Producer-Consumer)”模型,主要讨论的是进程(线程)间的互斥和同步问题,关键是对锁(lock)的申请、独占和释放,在这里我就不罗嗦了。原先我写的Java代码如下:
public class Producer extends Thread{
private ProductList products = ProductList.getInstance();
public void run(){
int i = 0;
while(i <= 20){
synchronized(products){ // Get lock on product list
if(products.isFull()){
System.out.println("List is full");
products.notify(); // Release the lock
} else{
Product product = new Product(i++); // Produce a product
products.put(product);
System.out.println("Produced product " + product.getId());
products.notify(); // Release lock
}
} // Release the lock
}
}
}
public class Consumer extends Thread{
ProductList products = ProductList.getInstance();
public void run(){
while(true){
synchronized(products){
try {
products.wait(); // Wait for lock
Product product = null;
if(!(products.isEmpty()))
product = products.take();
else
System.out.println("List is empty");
System.out.println("Consumed product " + product.getId()); // Get the lock
} catch (InterruptedException ex) {
ex.printStackTrace();
}
} // Release the lock
}
}
}
import java.util.ArrayList;
import java.util.List;
public class ProductList {
private static ProductList instance = new ProductList();
private List<Product> products; // Adapter pattern
public static final int SIZE = 10;
private ProductList() {
products = new ArrayList<Product>(SIZE);
}
public static ProductList getInstance() { // Singleton pattern
return instance;
}
public boolean isFull() {
return products.size() == SIZE;
}
public void put(Product product) {
products.add(product);
}
public Product take() {
return products.remove(0);
}
public boolean isEmpty() {
return products.isEmpty();
}
}
public class Product {
private int id;
public Product(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
public class Main {
public static void main(String[] args){
Producer p = new Producer();
Consumer c = new Consumer();
p.start();
c.start();
}
}
虽然Java对信号量及原语做了更高层次的封装(wait()、notify()、notifyAll()、synchronized{}),但看完上述代码还是觉得有点麻烦,于是JDK 5在原先collection框架的基础上增加了java.util.concurrent包,封装了许多用于线程并发操作的数据结构和操作。其中的BlockingQueue接口就是封装了一个阻塞队列的接口,具体地说就是实现了一个用于消费者(多个)和生产者(多个)交换产品的中介,生产者线程在队列满时阻塞,消费者线程在队列空时阻塞,当然在没有得到锁之前两类线程均会阻塞。详细信息可以参考Java Doc。下面用BlockingQueue实现P-C模型:
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) { queue.put(produce()); }
} catch (InterruptedException ex) {/* handle */}
}
Object produce() {/*... */}
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while(true) { consume(queue.take()); }
} catch (InterruptedException ex) { /* handle */ }
}
void consume(Object x) {/*...*/ }
}
class Setup {
void main() {
BlockingQueue q = new SomeQueueImplementation();
Producer p = new Producer(q);
Consumer c1 = new Consumer(q);
Consumer c2 = new Consumer(q);
new Thread(p).start();
new Thread(c1).start();
new Thread(c2).start();
}
}
可以看出代码中没有出现wait()或notify()之类的原语操作,这些操作由concurrent框架负责封装。更全面的讨论可以参考《驯服 Tiger: 并发集合》(IBM)
分享到:
相关推荐
阻塞队列是Java中并发编程的一个重要组件,它属于Java.util.concurrent包中的一部分。阻塞队列的主要特点在于它支持两个额外的条件操作:当队列为空时,尝试从队列中取元素的操作会被阻塞,直到队列中出现新的元素;...
在Java并发编程中,Blocking Queue(阻塞队列)是一个非常重要的工具类,它结合了线程同步与队列数据结构,有效地实现了生产者消费者模式。 Blocking Queue接口位于java.util.concurrent包下,它提供了一种在多线程...
而阻塞队列(Blocking Queue)是Java并发包(java.util.concurrent)中的一种高效数据结构,常用于线程间的协作,它能够简化同步问题并提高系统性能。 阻塞队列是一种特殊的队列,当队列为空时,取出元素的操作将会...
阻塞队列(Blocking Queue)是线程安全的数据结构,它结合了队列的先进先出(FIFO)原则和等待机制。当队列为空时,尝试获取元素的线程会被阻塞,直到队列中有新的元素;当队列满时,尝试插入元素的线程也会被阻塞,...
在Spring MVC框架中,`BlockingQueue`是一种常用于并发编程的数据结构,它是Java并发包`java.util.concurrent`下的核心组件。`BlockingQueue`是线程安全的队列,它提供了在生产者和消费者之间同步数据的方法,使得一...
Java 阻塞队列(Blocking Queue)是一种特殊类型的并发数据结构,它在多线程编程中扮演着重要的角色。阻塞队列的核心特性在于其在队列为空或满时能够自动阻塞线程,从而实现线程间的同步和通信。这种机制使得生产者...
在Java编程中,阻塞队列(Blocking Queue)是一种线程安全的数据结构,它在并发编程中扮演着重要角色,用于实现生产者消费者模型。通常,Java中的阻塞队列如`ArrayBlockingQueue`、`LinkedBlockingQueue`等都是内存...
在Java平台中,`java.util.concurrent`包提供了丰富的工具来支持高效的多线程编程,其中`BlockingQueue`接口便是其中之一。它提供了一种线程安全的方式来存储和检索对象,特别适用于生产者-消费者模式等场景。 ####...
- **并发队列(Concurrent Queue)**:在多线程环境中,允许多个线程同时进行入队和出队操作,通常需要复杂的同步机制,如Java的`java.util.concurrent`包中的队列。 通过分析这个项目的代码,我们可以学习到如何在...
在Java编程语言中,"优先阻塞队列"(Priority Blocking Queue)是一个高效且功能强大的数据结构,它结合了队列的先进先出(FIFO)原则与堆的优先级特性。优先阻塞队列主要用在多线程环境中,为并发处理提供了便利。...
Java的并发编程框架提供了多种高级并发工具,其中BlockingQueue是一种非常实用的数据结构,它实现了生产者-消费者模式。在多线程环境下,BlockingQueue可以高效地处理线程间的通信,确保数据的安全共享。本文将深入...
- **阻塞队列(Blocking Queue)**:在多线程环境中,当队列为空时,出队操作会阻塞,直到有新的元素入队;当队列满时,入队操作也会阻塞,直到有元素被出队。这在并发编程中非常有用,如Java的`java.util....
14. **阻塞队列(Blocking Queue)和阻塞栈(Blocking Stack)**:Java并发包中的LinkedBlockingQueue和ArrayBlockingQueue是典型的阻塞队列实现,它们在插入和移除元素时能自动处理线程阻塞。Deque接口的实现如...
- `java.util`包:包含集合框架、日期时间、泛型、队列、栈、排序等工具类,如ArrayList、HashMap、LinkedList等。 2. **Java集合框架**: - 集合接口:如List、Set、Queue,以及它们的实现类如ArrayList、...
Enlfq 使用以下库的简单NIF无锁队列: moodycamel :: ConcurrentQueue C ++的工业强度无锁队列。 特点: 击倒你的袜子,快速的表现。 单头实现。 只需将其放入您的项目中即可。 完全线程安全的无锁队列。 从任何数量...
3. **阻塞队列(Blocking Queue)**:这是一种特殊的队列,当队列满时,添加元素的尝试会阻塞,直到队列有空间;当队列空时,获取元素的尝试会阻塞,直到队列中有元素。Java的`java.util.concurrent`包提供了`...
4. 队列:包括阻塞队列(Blocking Queue)和生产者-消费者模型,线程可以在队列中放入或取出元素,达到同步和通信的目的。 5. 管道(Pipe)和通道(Channel):在某些系统中,线程可以通过管道或通道直接传递数据,...
在多线程编程中,生产者与消费者模式是一种经典的并发设计模式,...在实际编程时,可以根据需求选择合适的阻塞队列实现,如Python的`multiprocessing.Queue`或`concurrent.futures.Queue`等,以适应不同的并发场景。
1. **阻塞队列(Blocking Queue)**:Java中的`BlockingQueue`接口提供了`put()`和`take()`方法。当队列满时,`put()`方法会阻塞生产者线程,直到有空间可用;同样,当队列空时,`take()`方法会阻塞消费者线程,直到...