Java中的BlockingQueue是一种支持线程安全的队列,它提供了一种基于阻塞的队列操作方式。具体来说,当队列为空时,从队列中获取元素的操作将被阻塞,直到队列中有新的元素添加;当队列已满时,向队列中添加元素的操作将被阻塞,直到队列中有空闲位置。
BlockingQueue接口提供了以下几个常用方法:
put(E e): 向队列中添加一个元素,如果队列已满,则会一直阻塞等待直到队列有空闲位置。
take(): 从队列中获取并删除一个元素,如果队列为空,则会一直阻塞等待直到队列中有元素可取。
offer(E e, long timeout, TimeUnit unit): 向队列中添加一个元素,并在指定的时间内等待队列空闲,如果在指定时间内队列还是满的,则返回false。
poll(long timeout, TimeUnit unit): 从队列中获取并删除一个元素,并在指定的时间内等待队列非空,如果在指定时间内队列还是空的,则返回null。
下面是一个使用BlockingQueue实现生产者-消费者模式的代码示例:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class ProducerConsumerExample {
public static void main(String[] args) {
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
Thread producer = new Thread(new Producer(queue));
Thread consumer = new Thread(new Consumer(queue));
producer.start();
consumer.start();
}
}
class Producer implements Runnable {
private BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("Produced: " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer implements Runnable {
private BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
Integer value = queue.take();
System.out.println("Consumed: " + value);
Thread.sleep(2000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在上面的例子中,Producer类和Consumer类分别实现了Runnable接口,并在run()方法中分别调用BlockingQueue的put()和take()方法来添加和获取元素。当队列已满时,生产者线程会被阻塞,直到队列有空闲位置;当队列为空时,消费者线程会被阻塞,直到队列中有元素可取。这种基于阻塞的队列操作方式可以很好地解决多线程并发访问队列时的线程安全问题。