package cn.bufanli.test.Queue;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 使用wait(等待)/notify(通知) 模拟queue
* BlockingQueue(阻塞队列):顾名思义,首先它是一个队列,并且支持阻塞的机制,阻塞的放和阻塞的得到数据
* 我们要实现LinkedBlockingQueue下面两个简单的方法 put 和take
* put(Object):把anObject 加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断
* 直到BlockingQueue里面有空间再继续
* take:取走BlockingQueue里排在首位的对象,若BlockingQueue位空,区段进入等待状态
*/
public class MyQueue {
/**
* 1.需要一个存放元素的集合
*/
private LinkedList<Object> list = new LinkedList<Object>();
/**
* 2.需要一个计数器
*/
private AtomicInteger count = new AtomicInteger(0);
/**
* 3.需要定义一个上限和下限
*/
private final int minSize = 0;
private final int maxSize;
/**
* 4.构造方法
* @param size
*/
public MyQueue(int size) {
this.maxSize = size;
}
/**
* 5.创建一个对象用于加锁
*/
private final Object lock = new Object();
/**
* 把一个对象追加到BlockingQueue里,如果BlockingQueue里面
* 没有空间,则调用此方法的线程被阻断,直到BlockingQueue里面有空间再继续
*
* @param obj
*/
public void put(Object obj) {
synchronized (lock) {
while (count.get() == this.maxSize) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
//加入元素
list.add(obj);
//计数器累加
count.incrementAndGet();
//通知另外一个线程(唤醒)
lock.notify();
System.out.println("新加入的元素为:" + obj);
}
}
/**
* 取走BlockingQueue里面排在首位的对象,若BlockingQueue为空,阻断进入等到状态
* 直到BlockingQueue有新的数据被加入
*
* @return
*/
public Object take() {
Object ret = null;
synchronized (lock) {
//队列里没有数据等待唤醒
while (count.get() == this.minSize) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
//做移出元素操作
ret = list.removeFirst();
//计数器递减
count.decrementAndGet();
//唤醒另外一个程序
lock.notify();
}
return ret;
}
public int getSize() {
return this.count.get();
}
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");
Thread t1 = new Thread(() -> {
mq.put("f");
mq.put("g");
}, ("t1"));
t1.start();
Thread t2 = new Thread(() -> {
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();
}
}
打印