/**
*生产者-消费者与队列
*制作吐司的例子,先向干吐司抹黄油,再在抹过黄油的吐司上涂果酱
*本例子没有使用任何显式的同步,而是利用阻塞队列来实现同步
*每片吐司在任何时刻都只由一个任务在操作
*
* @author c
* @data 2016-08-31
* @modify
*
*/
class Toast {
public enum Status {
DRY, BUTTERED, JAMMED
}
private Status status = Status.DRY;
private final int id;
public Toast(int idn) {
id = idn;
}
public void buffer() {
status = Status.BUTTERED;
}
public void jam() {
status = Status.JAMMED;
}
public Status getStatus() {
return status;
}
public int getId() {
return id;
}
public String toString() {
return "Toast " + id + ": " + status;
}
}
class ToastQueue extends LinkedBlockingQueue<Toast> {
}
class Toaster implements Runnable {
private ToastQueue toastQueue;
private int count = 0;
private Random rand = new Random(47);
public Toaster(ToastQueue tq) {
toastQueue = tq;
}
public void run() {
try {
while (!Thread.interrupted()) {
TimeUnit.MILLISECONDS.sleep(100 + rand.nextInt(500));
// 制作吐司
Toast t = new Toast(count++);
print(t);
// 插入队列
toastQueue.put(t);
}
} catch (InterruptedException e) {
print("Toaster interrupted");
}
print("Toaster off");
}
}
// 给吐司抹黄油
class Butterer implements Runnable {
private ToastQueue dryQueue, butteredQueue;
public Butterer(ToastQueue dry, ToastQueue buttered) {
dryQueue = dry;
butteredQueue = buttered;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
// 阻塞直到下一份可利用的吐司
Toast t = dryQueue.take();
t.buffer();
print(t);
butteredQueue.put(t);
}
} catch (InterruptedException e) {
print("Butterer interrupted");
}
print("Butterer off");
}
}
// 在抹过黄油的吐司上涂果酱
class Jammer implements Runnable {
private ToastQueue butteredQueue, finishedQueue;
public Jammer(ToastQueue buttered, ToastQueue finished) {
butteredQueue = buttered;
finishedQueue = finished;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
// 阻塞直到下一份吐司可以利用
Toast t = butteredQueue.take();
t.jam();
print(t);
finishedQueue.put(t);
}
} catch (InterruptedException e) {
print("Jammer interrupted");
}
print("Jammer off");
}
}
// 消费吐司
class Eater implements Runnable {
private ToastQueue finishedQueue;
private int counter = 0;
public Eater(ToastQueue finished) {
finishedQueue = finished;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
// 阻塞直到下一份吐司可以利用
Toast t = finishedQueue.take();
// 确认吐司按顺序到来和所有吐司都抹了果酱
if (t.getId() != counter++ || t.getStatus() != Toast.Status.JAMMED) {
print(">>>> Error " + t);
System.exit(1);
} else
print("chomp!" + t);
}
} catch (InterruptedException e) {
print("Eater interrupted");
}
print("Eater off");
}
}
public class ToastOMatic {
public static void main(String[] args) throws Exception {
ToastQueue dryQueue = new ToastQueue(), butteredQueue = new ToastQueue(), finishedQueue = new ToastQueue();
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Toaster(dryQueue));
exec.execute(new Butterer(dryQueue, butteredQueue));
exec.execute(new Jammer(butteredQueue, finishedQueue));
exec.execute(new Eater(finishedQueue));
TimeUnit.SECONDS.sleep(5);
exec.shutdownNow();
}
}
生产者-消费者与队列的简单示例
最新推荐文章于 2023-12-07 16:44:02 发布