工厂类:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Depot {
private int depotSize; // 仓库大小
private Lock lock; // 独占锁
private int capacity; // 仓库容量
private Condition fullCondition;
private Condition emptyCondition;
public Depot() {
this.depotSize = 0;
this.lock = new ReentrantLock();
this.capacity = 15;
// 为锁加上两个条件
this.fullCondition = lock.newCondition();
this.emptyCondition = lock.newCondition();
}
public void put(int value) {
lock.lock(); // 上锁
try {
int left = value;
while(left > 0) {
// 库存已经满时,“生产者”等待“消费者”消费
while(depotSize >= capacity) {
fullCondition.await();
}
// 获取实际入库数量:预计库存(仓库现有库存 + 生产数量) > 仓库数量 ? 仓库数量 - 仓库现有库存 : 生产数量
int inc = depotSize + left > capacity ? capacity - depotSize : left;
depotSize += inc;
left -= inc;
System.out.println(Thread.currentThread().getName()
+ " -> 要入库的数量:" + value
+ " -> 实际入库数量:" + inc
+ " -> 仓库货物数量:" + depotSize
+ " -> 没有入库数量:" + left);
// 通知消费者可以消费了
emptyCondition.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); // 卸锁
}
}
public void get(int value) {
lock.lock();
try {
int left = value;
while(left > 0) {
// 仓库已空,“消费者”等待“生产者”生产货物
while(depotSize <= 0) {
emptyCondition.await();
}
// 实际消费:仓库库存数量 < 要消费数量 ? 仓库库存数量 : 要消费数量
int dec = depotSize < left ? depotSize : left;
depotSize -= dec;
left -= dec;
System.out.println(Thread.currentThread().getName()
+ " -> 要消费的数量:" + value
+ " -> 实际消费数量:" + dec
+ " -> 仓库现存数量:" + depotSize
+ " -> 未获取的数量:" + left);
// 通知生产者可以生产了
fullCondition.signal();
}
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
生产者:
public class Producer {
private Depot depot;
public Producer(Depot depot) { this.depot = depot; }
public void produce(final int value) {
new Thread() {
@Override
public void run() {
depot.put(value);
}
}.start();
}
}
消费者:
public class Consumer {
private Depot depot;
public Consumer(Depot depot) { this.depot = depot; }
public void consume(final int value) {
new Thread() {
@Override
public void run() {
depot.get(value);
}
}.start();
}
}