版权声明:博观而约取,厚积而薄发。 https://blog.csdn.net/BruceLiu_code/article/details/88375381
BlockingQueue:顾名思义,首先它是一个队列,然后支持阻塞机制。阻塞的放入和得到的数据。如果我们要实现LinkedBlockingQueue,那么最起码要实现两个最为基础的方法:put和tack。
- put:把anObject加入到BlockingQueue中,如果队列中没有空间,则调用此方法的线程被阻塞,直到BlockingQueue中有可用的空间再继续加入。
- tabk:获取BlockingQueue中排在首位的对象,弱BlockingQueue为空,则阻塞进入等待的状态。直到BlockingQueue有新的数据被加入。
示例:
/**
* 使用wait和notify模拟BlockingQueue
* @author bruceliu
* @create 2019-03-10 10:21
*/
public class MyQueue {
//1.定义一个空的元素集合
private LinkedList<Object> list=new LinkedList<Object>();
//2.定义一个计数器
private AtomicInteger count=new AtomicInteger();
//3.定义上限和下限
private final int minSize=0;
private int maxSize;
//4.定义构造方法
public MyQueue(int size){
this.maxSize=size;
}
//5.初始化一个对象,用作加锁
private final Object lock=new Object();
//put(anObject): 把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续.
public void put(Object object){
synchronized (lock){
while(count.get()==this.maxSize){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//1.加入元素
list.add(object);
//2.计数器累加
count.incrementAndGet();
//3.通知另外一个线程 唤醒
lock.notify();
System.out.println("新加入的元素为:"+object);
}
}
//take: 取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入.
public Object take(){
Object object=null;
synchronized (lock){
while(count.get()==this.minSize){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//1.移除元素
object=list.removeFirst();
//2.计数器递减
count.decrementAndGet();
//3.唤醒另外一个线程
lock.notify();
}
return object;
}
//获取集合大小
public int getSize(){
return this.count.get();
}
}
测试:
/**
* 测试自定义阻塞队列
* @author bruceliu
* @create 2019-03-10 10:48
*/
public class TestMyQueue {
public static void main(String[] args) {
final MyQueue mq=new MyQueue(5);
mq.put("a");
mq.put("b");
mq.put("c");
mq.put("d");
mq.put("e");
System.out.println("当前容器的长度是:"+mq.getSize());
Thread t1=new Thread(new Runnable() {
public void run() {
mq.put("f");
mq.put("g");
}
},"t1");
t1.start();
Thread t2=new Thread(new Runnable() {
public void run() {
Object o1=mq.take();
System.out.println("移除的元素为:"+o1);
Object o2=mq.take();
System.out.println("移除的元素为:"+o2);
}
},"t2");
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
}
事实上,在JavaJDK中已经有了LinkedBlockingQueue这样一个阻塞队列,在此模拟一下是方便更好的理解阻塞队列。
如果有兴趣,可以看看LinkedBlockingQueue的源码。