1. 阻塞隊列
阻塞隊列(BlockingQueue)是一個支持兩個附加操作的隊列。這兩個附加的操作是:
- 在隊列爲空時,獲取元素的線程會等待隊列變爲非空。
- 當隊列滿時,存儲元素的線程會等待隊列可用。
當阻塞隊列滿時,如果生產者線程使用put方法向隊列中添加元素,隊列會一直阻塞生產者線程,直到拿到數據,或者響應中斷退出。當隊列空時,消費者使用take方法從隊列中獲取元素,隊列也會阻塞消費者線程,直到隊列可用。
2. 阻塞隊列實現生產者和消費者實例
生產者線程,ProducerThread.java:
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* 生產者線程
* @author syrdbt
* @date 2020-02-26
*/
public class ProducerThread implements Runnable{
private LinkedBlockingQueue blockingQueue;
public ProducerThread(LinkedBlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
Random random = new Random();
while (true) {
try {
this.produce(random.nextInt(5));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void produce(int productNumber) throws InterruptedException {
TimeUnit.SECONDS.sleep(productNumber);
blockingQueue.put(productNumber);
System.out.println("【生產者】生產了" + productNumber + "號產品,花費了" + productNumber + "秒,成功的添加"
+ productNumber + "產品到了隊列中");
}
}
消費者線程,ConsumerThread.java:
/**
* 消費者線程
* @author syrdbt
* @date 2020-02-26
*/
public class ConsumerThread implements Runnable{
private LinkedBlockingQueue blockingQueue;
public ConsumerThread(LinkedBlockingQueue blockingQueue) {
this.blockingQueue = blockingQueue;
}
@Override
public void run() {
Random random = new Random();
while (true) {
try {
this.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void consume() throws InterruptedException {
int productNumber = (int) blockingQueue.take();
TimeUnit.SECONDS.sleep(productNumber);
System.out.println("【消費者】消費了" + productNumber + "號產品,花費了" +
productNumber + "秒,成功的從隊列中取出" + productNumber + "號產品");
}
}
測試程序,Main.java:
import java.util.concurrent.LinkedBlockingQueue;
/**
* @author syrdbt
* @date 2020-02-26
*/
public class Main {
public static void main(String[] args) {
LinkedBlockingQueue blockingQueue = new LinkedBlockingQueue();
Thread producerThread = new Thread(new ProducerThread(blockingQueue));
Thread consumerThread = new Thread(new ConsumerThread(blockingQueue));
producerThread.start();
consumerThread.start();
}
}
測試程序運行截圖如下: