BlockingQueue阻塞队列:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素
队列FIFO先进先出 一端写入一端取出
写入如果队列满了就必须阻塞等待,如果队列是空的必须阻塞等待生产
注意:BlockingQueue不接受null值,试图添加一个null元素时会抛出异常。BlockingQueue 可以是限定容量的 超过给定容量时是无法添加的
BlockingQueue的四种API
ArrayBolckingQueue:基于数组的有界阻塞队列
阻塞队列核心方法
方法类型 | 抛出异常 | 特殊值( 有返回值) | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add | offer | put | offer |
移除 | remove | poll | take | poll |
判断队列首 | element | peek | - | - |
ArrayBolckingQueue使用示例:
第一组会抛出异常API演示
public static void test(){
//自定义数组队列的数量
ArrayBlockingQueue blockingDeque=new ArrayBlockingQueue<>(3);
//add添加成功返回true
System.out.println(blockingDeque.add("a"));
System.out.println(blockingDeque.add("b"));
System.out.println(blockingDeque.add("c"));
//取队列首元素
System.out.println(blockingDeque.element());
//超过队列大小 add会抛出异常 Queue full
// System.out.println(blockingDeque.add("d"));
System.out.println("===============================");
//remove取出一个元素 返回取出的值 如果队列为空 remove会抛出异常
System.out.println(blockingDeque.remove());
System.out.println(blockingDeque.remove());
System.out.println(blockingDeque.remove());
}
第二组特殊值( 有返回值)API使用
/**
* 返回值
*/
public static void test1(){
//自定义数组队列的数量
ArrayBlockingQueue blockingDeque=new ArrayBlockingQueue<>(3);
//offer添加元素,如果添加成功会返回true
System.out.println(blockingDeque.offer("a"));
System.out.println(blockingDeque.offer("b"));
System.out.println(blockingDeque.offer("c"));
//当越界时添加元素,会返回false,不会抛出异常
System.out.println("===================");
System.out.println(blockingDeque.offer("d"));
//peek取队列头元素
System.out.println(blockingDeque.peek());
System.out.println("===================");
//取数组队列元素
System.out.println(blockingDeque.poll());
System.out.println(blockingDeque.poll());
System.out.println(blockingDeque.poll());
}
第三组阻塞API使用
/**
* 等待 一直阻塞
*/
public static void test2() throws InterruptedException {
//自定义数组队列的数量
ArrayBlockingQueue blockingQueue=new ArrayBlockingQueue<>(3);
//添加到队列
blockingQueue.put("a");
blockingQueue.put("b");
blockingQueue.put("c");
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
//如果超出数组队列的范围就会等待
System.out.println(blockingQueue.take());
}
第四组API使用设置阻塞时间 超过阻塞时间没放进去就放弃等待
public static void test3() throws InterruptedException {
//自定义数组队列的数量
ArrayBlockingQueue blockingDeque=new ArrayBlockingQueue<>(3);
//offer添加元素,如果添加成功会返回true
System.out.println(blockingDeque.offer("a"));
System.out.println(blockingDeque.offer("b"));
System.out.println(blockingDeque.offer("c"));
//等待2秒后退出
System.out.println(blockingDeque.offer("d",2, TimeUnit.MILLISECONDS));
//peek取队列头元素
System.out.println(blockingDeque.peek());
System.out.println("===================");
//取数组队列元素
System.out.println(blockingDeque.poll());
System.out.println(blockingDeque.poll());
System.out.println(blockingDeque.poll());
//等待2秒后退出
blockingDeque.poll(10,TimeUnit.MILLISECONDS);
}
SynchronousQueue同步队列
/**
* 和其他BlockingQueue不一样,SynchronousQueue不存储元素
* put进一个元素,就必须take取出来,否则不能继续put
* @param args
*/
public static void main(String[] args) {
//同步队列
BlockingQueue<String> blockingQueue=new SynchronousQueue<>();
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName()+"=> put 1");
blockingQueue.put("1");
System.out.println(Thread.currentThread().getName()+"=> put 2");
blockingQueue.put("2");
System.out.println(Thread.currentThread().getName()+"=> put 3");
blockingQueue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T1").start();
new Thread(()->{
try {
Thread.sleep(3);
System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
Thread.sleep(3);
System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
Thread.sleep(3);
System.out.println(Thread.currentThread().getName()+"=>"+blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"T2").start();
}