一、概述
BlockingQueue在java.util.concurrent包
首先是是一个队列,其实在多线程环境下自动阻塞或唤醒
BlockingQueue 具有 4 组不同的方法用于插入、移除以及对队列中的元素进行检查。如果请求的操作不能得到立即执行的话,每个方法的表现也不同。这些方法如下:
抛出异常 | 特殊值 | 阻塞 | 超时 | |
插入 | add(e) | offer(e) | put(e) | offer(e, time, unit) |
移除 | remove() | poll() | take() | poll(time, unit) |
检查 | element() | peek() | 不可用 | 不可用 |
四组不同的行为方式解释:
1(异常)
如果试图的操作无法立即执行,抛一个异常。
2(特定值)
如果试图的操作无法立即执行,返回一个特定的值(常常是 true / false)。
3(阻塞)
如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行。
4(超时)
如果试图的操作无法立即执行,该方法调用将会发生阻塞,直到能够执行,但等待时间不会超过给定值。返回一个特定值以告知该操作是否成功(典型的是 true / false)。
二、测试代码
生产者/消费者
package com.example.blockingQueue;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Run {
public static void main(String[] args) throws InterruptedException {
System.out.println("main start");
BlockingQueue queue = new ArrayBlockingQueue(2);
Producer producer = new Producer(queue);
producer.start();
Thread.sleep(5000);
Consumer consumer = new Consumer(queue);
consumer.start();
System.out.println("main ok");
}
}
/**
* 消息生产者
*/
class Producer extends Thread {
private int count = 1;
private BlockingQueue queue;
public Producer(BlockingQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
Thread.sleep(500);
String message = "hello" + count++;
queue.add(message);//抛出异常
System.out.println(TimeUtils.getCurrentTime() + "生产者:开始,message:" + message + ",queue:" + queue.size());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 消息消费者
*/
class Consumer extends Thread {
private BlockingQueue queue;
public Consumer(BlockingQueue queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
System.out.println(TimeUtils.getCurrentTime() + "消费者:" + queue.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class TimeUtils {
public static String getCurrentTime() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss S").format(new Date());
}
}
运行结果:
queue.add(message);//抛出异常
main start
2022-01-19 23:53:32 850生产者:开始,message:hello1,queue:1
2022-01-19 23:53:33 351生产者:开始,message:hello2,queue:2
java.lang.IllegalStateException: Queue full
at java.util.AbstractQueue.add(AbstractQueue.java:98)
at java.util.concurrent.ArrayBlockingQueue.add(ArrayBlockingQueue.java:312)
at com.example.blockingQueue.Producer.run(Run.java:42)
main ok
2022-01-19 23:53:37 313消费者:hello1
2022-01-19 23:53:37 314消费者:hello2
修改代码
queue.put("hello"+ count);//阻塞
运行结果
main start
2022-01-20 00:11:29 112生产者:开始,message:hello1,queue:1
2022-01-20 00:11:29 613生产者:开始,message:hello2,queue:2
main ok
2022-01-20 00:11:33 577消费者:hello2
2022-01-20 00:11:33 578生产者:开始,message:hello3,queue:2
2022-01-20 00:11:33 578消费者:hello3
2022-01-20 00:11:33 579消费者:hello4
2022-01-20 00:11:33 580消费者:hello5
2022-01-20 00:11:34 78生产者:开始,message:hello4,queue:0
2022-01-20 00:11:34 78消费者:hello6
2022-01-20 00:11:34 578生产者:开始,message:hello5,queue:0
2022-01-20 00:11:34 578消费者:hello7
2022-01-20 00:11:35 79生产者:开始,message:hello6,queue:0
2022-01-20 00:11:35 79消费者:hello8
2022-01-20 00:11:35 579生产者:开始,message:hello7,queue:0