阻塞队列BlockingQueue,在容器满的时候,放入元素,会被阻塞,等到容器中元素被取走时,才可以放入;当容器为空的时候,无法从容器取出元素,当有元素放入时,才可以从容器中取走。
/**
* 模拟阻塞队列
*/
public class MyQueue {
// 1、定义容器
privateLinkedList<Object> list = newLinkedList<Object>();
// 2、设置最小和最大容量
private int minSize = 0;
private int maxSize;
// 3、设置计数器
private AtomicInteger count = newAtomicInteger(0);
// 4、对象锁,这里一把锁,就可以实现,因为不可能同时阻塞
private final Object lock = new Object();
// 在声明对象时,给队列长度赋值
public MyQueue(int maxSize) {
this.maxSize = maxSize;
}
/*
*put()把对象加入BlockingQueue中,如果BlockQueue没有空间,则
* 调用此方法的线程被阻塞,知道BlockingQueue里面有空间再继续
*/
public voidput(Object obj) {
synchronized (lock) {
while (count.get() == this.maxSize) {// 如果队列放满了,则阻塞
try {
lock.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
list.add(obj);
count.incrementAndGet();
lock.notify();
System.out.println("放入了元素:" + obj);
}
}
/*
* 取走BlockingQueue里排在首位的对象,如果为空BlockingQueue为空,则阻塞进入等待状态直到里有新的数据加入
*/
public Object take() {
Object ret = null;
synchronized (lock) {
while (count.get() == this.minSize) {
try {
lock.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
ret = list.removeFirst();
lock.notify();
count.decrementAndGet();
System.out.println("取出了元素:" + ret);
}
return ret;
}
public static voidmain(String[] args) {
final MyQueue mq = newMyQueue(5);
mq.put("a");
mq.put("b");
mq.put("c");
mq.put("d");
mq.put("e");
// 放入两个元素,
new Thread(newRunnable() {
@Override
public void run() {
mq.put("e");
mq.put("f");
}
}).start();
// 休眠2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch(InterruptedException e) {
e.printStackTrace();
}
new Thread(newRunnable() {
@Override
public void run() {
mq.take();
mq.take();
}
}).start();
}
}