阻塞队列能是⼀种
线程安全的数据结构
, 并且具有以下特性:
•
当队列满的时候, 继续⼊队列就会阻塞, 直到有其他线程从队列中
取⾛
元素.
•
当队列空的时候, 继续出队列也会阻塞, 直到有其他线程往队列中
插⼊
元素
标准库中的阻塞队列
在 Java 标准库中内置了阻塞队列. 如果我们需要在⼀些程序中使⽤阻塞队列, 直接使⽤标准库中的
•
BlockingQueue 是⼀个接⼝. 真正实现的类是 LinkedBlockingQueue.
•
put ⽅法⽤于阻塞式的⼊队列, take ⽤于阻塞式的出队列.
•
BlockingQueue 也有 offer, poll, peek 等⽅法, 但是这些⽅法不带有阻塞特性.

阻塞队列实现
•
通过 "循环队列" 的⽅式来实现.
•
使⽤ synchronized 进⾏加锁控制.
•
put 插⼊元素的时候, 判定如果队列满了, 就进⾏ wait. (注意, 要在循环中进⾏ wait. 被唤醒时不⼀定
队列就不满了, 因为同时可能是唤醒了多个线程).
•
take 取出元素的时候, 判定如果队列为空, 就进⾏ wait. (也是循环 wait)
class MyBlockingQueue{ private int size=0; private int head=0; private int last=0; private String[] data=null; public MyBlockingQueue(int num){ data=new String[num]; } public void put(String num1) throws InterruptedException { synchronized (this){ while(size>=data.length){ this.wait(); } data[last]=num1; last++; if(last>=data.length){ last=0; } size++; this.notify(); } } public String talk() throws InterruptedException { synchronized (this){ while(size==0){ this.wait();//防止提前唤醒 } String arr=data[head]; head++; if(head>=data.length){ head=0; } size--; this.notify(); return arr; } } } public class work1 { public static void main(String[] args) throws InterruptedException { MyBlockingQueue block1=new MyBlockingQueue(1000); Thread t1=new Thread(()->{ while(true){ try { System.out.println("消费元素"+block1.talk()); Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); Thread t2=new Thread(()->{ int num2=0; while(true){ try { num2++; block1.put(num2+""); System.out.println("生产元素"+num2); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); t1.start(); t2.start();
}