队列可以使用数组或链表进行实现,这里使用数组模拟队列
队列有一个最大容量 maxSize,并且有两个变量 front 和 rear 分别用来记录队列前后端的下标
public class BlockingQueueDemo {
public static void main(String[] args) {
BlockingQueue blockingQueue = new BlockingQueue(1000);
new Thread(()->{
for (int i = 1; i <= 100; i++) {
try {
blockingQueue.put(i);
Thread.sleep((long)Math.random() * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Thread1").start();
new Thread(() -> {
while (true) {
try {
int take = blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Thread--2").start();
new Thread(() -> {
while (true) {
try {
int take = blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Thread--3").start();
}
}
class BlockingQueue {
private int[] queue; // 存放数据,模拟队列
private volatile int maxSize; // 最大容量
private volatile int front; // 队列头部数据再向前一位位置
private volatile int rear; // 指向队列尾部最后一个数据位置
public BlockingQueue (int maxSize) {
this.maxSize = maxSize;
queue = new int[maxSize];
front = -1;
rear = -1;
}
// 判断队列是否已满
public boolean isFull() {
return rear == maxSize - 1;
}
// 判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
// 队列操作:入队列
public synchronized void put(int value) throws InterruptedException {
// 队列满,阻塞
while (isFull()) {
System.out.printf("队列满,%s正在等待\n", Thread.currentThread().getName());
this.wait();
}
// 队列空,唤醒所有阻塞线程
if (isEmpty()) {
notifyAll();
}
// 入队列
rear++;
queue[rear] = value;
this.notify();
System.out.printf("%s向队列中添加数据%d成功\n", Thread.currentThread().getName(), queue[rear]);
}
// 队列操作:出队列
public synchronized int take() throws InterruptedException {
// 队列为空,阻塞
while (isEmpty()) {
System.out.printf("队列空,%s正在等待~~~\n", Thread.currentThread().getName());
this.wait();
}
if (isFull()) {
notifyAll();
}
front++;
notify();
System.out.printf("%s从队列中取出元素%d\n", Thread.currentThread().getName(), queue[front], queue.length);
return queue[front];
}
}