代码
package com.example.KFC;
public class Cooker extends Thread { public void run() { while (true) { synchronized (Desk.lock) { if (Desk.maxCount == 0) { break; } else { if (!Desk.flag) { System.out.println("Cooker makes a hamburger"); Desk.flag = true; Desk.lock.notifyAll(); } else { try { Desk.lock.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } }
}
package com.example.KFC;
public class Foodie extends Thread { public void run() { while (true) { synchronized (Desk.lock) { if (Desk.maxCount == 0) { System.out.println("Foodie is out of food"); break; } else { if (Desk.flag) { Desk.maxCount--; System.out.println("Foodie eats a hamburger and have " + Desk.maxCount + " hamburger to eat left"); Desk.flag = false; Desk.lock.notifyAll(); } else { try { Desk.lock.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } } }
}
package com.example.KFC;
public class Desk { public static boolean flag = false; public static int maxCount = 10; static Object lock = new Object();
}
package com.example.KFC;
public class Demo { public static void main(String[] args) { Foodie f = new Foodie(); Cooker c = new Cooker(); f.start(); c.start(); }
}
背景介绍
这四个程序是一个简单的生产者消费者模型的实现,用于模拟厨师(生产者)制作汉堡,食客(消费者)吃汉堡的过程。
Desk.java:这是一个共享资源类,包含了一个标志位flag,一个最大计数器maxCount和一个锁对象lock。flag用于标记是否有汉堡可供食客吃,maxCount用于记录还剩下多少汉堡,lock用于同步厨师和食客的行为。
Cooker.java:这是厨师类,继承了Thread类。在其run方法中,厨师会不断地制作汉堡,直到maxCount为0。如果flag为false,表示没有汉堡,厨师就会制作一个汉堡,并将flag设为true,然后唤醒所有在lock上等待的线程(即食客)。如果flag为true,表示有汉堡,厨师就会在lock上等待。
Foodie.java:这是食客类,也继承了Thread类。在其run方法中,食客会不断地吃汉堡,直到maxCount为0。如果flag为true,表示有汉堡,食客就会吃掉一个汉堡,并将flag设为false,然后唤醒所有在lock上等待的线程(即厨师)。如果flag为false,表示没有汉堡,食客就会在lock上等待。
Demo.java:这是主程序类,创建了一个厨师线程和一个食客线程,并启动它们。
这四个程序共同模拟了一个生产者消费者问题的解决方案,通过wait和notifyAll方法以及同步块来保证厨师和食客的行为的同步性,避免了资源的浪费和冲突。
流程解读
一个“锁”上的多个线程在同一时间只能有一个处于运行态;
在本案例中,吃货和厨师在start后进入就绪态,随后吃货进入运行态,厨师在就绪态“排队”,随后吃货在run中notifyAll,随后他通过wait进入等待态,在就绪态准备的厨师进入运行态,执行厨师进程的run,在对Desk执行完方法后notiFyAll唤醒吃货使其进入就绪态排队,随后厨师通过wait进入等待态,在就绪态准备的吃货进入运行态,如此周而复始,一直到共享数据结束。