逻辑代码
/*
*
如果先获取队列的使用权限,而不是先判断空或者满的情况下:
* 死锁的执行顺序
* 1. 队列初始为满
* 2. 消费者首先执行,获取队列锁,但是empty锁已经锁住了
* 3. 生产者在执行,队列锁锁住了。
*
* 死锁执行顺序2
* 1. 队列初始为空
* 2. 生产者首先执行,获取队列锁,但是full锁已经上了
* 3. 消费者执行,队列锁拿不到。
* */
package leetcode;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Semaphore;
class BoundedBlockingQueue2 extends BoundedBlockingQueue{
Queue<Integer> queue = new LinkedList<>();
Semaphore full;
Semaphore empty;
Semaphore mutex;
public BoundedBlockingQueue2(int capacity) {
super(capacity);
full = new Semaphore(capacity);
empty = new Semaphore(0);
mutex = new Semaphore(1);
}
public void enqueue(int element) throws InterruptedException {
full.acquire();
mutex.acquire(1);
queue.add(element);
empty.release();
mutex.release();
}
public int dequeue() throws InterruptedException {
int x = 0;
empty.acquire();
mutex.acquire();
x = queue.poll();
full.release();
mutex.release();
return x;
}
public int size() {
int sz = 0;
try {
mutex.acquire();
sz = queue.size();
mutex.release();
} catch (Exception e){
e.printStackTrace();
}
return sz;
}
public void TestMutex() throws Exception{
mutex.acquire(1);
System.out.println("可以获得一把锁");
System.out.println("执行完成");
mutex.release();
}
public static void main(String[] args) {
String[] list = {"leetcode.BoundedBlockingQueue", "10"}; // 初始容量为10
try {
BoundBlockingQueMain.main(list);
} catch (Exception e) {
e.printStackTrace();
}
}
}
主测试代码,使用反射生成对象,可以测试不同的实现方式。
package leetcode;
import java.util.concurrent.ThreadLocalRandom;
public class BoundBlockingQueMain {
public static void main(String[] args) throws Exception{
BoundedBlockingQueue que = (BoundedBlockingQueue) Class.forName(args[0]).getDeclaredConstructor(int.class).newInstance(Integer.valueOf(args[1]));
for (int i = 0; i < 3; i++) {
// 3个生产者
String name = "producer_" + i;
new Thread(()->{
// 使用线程本地变量进行随机数的生产。
ThreadLocalRandom t = ThreadLocalRandom.current();
try {
while(true) {
if (que.enSub()) {
int x = t.nextInt(19);
que.enqueue(x);
System.out.println(Thread.currentThread().getName() + "生产了数字:" + x);
}
else break;
}
} catch (Exception e) {
e.printStackTrace();
}
}, name).start();
}
for (int i = 0; i < 4; i++) {
// 4个消费者
String name = "customer_" + i;
new Thread(()->{
try {
while(true) {
if (que.deSub()) {
int x = que.dequeue();
System.out.println(Thread.currentThread().getName() + "消费数字:" + x);
}
else break;
}
} catch (Exception e) {
e.printStackTrace();
}
}, name).start();
}
}
}