//第一个类用来定义客人类
public class Guest implements Runnable{
Plate plate;
public Guest(Plate plate) {
super();
this.plate = plate;
}
@Override
public void run() {
for (int i = 0; i < 6; i++) {
// System.out.println("客人第"+i+"次取用果盘中的水果");
plate.getFruit();
// System.out.println("客人第"+i+"次取完果盘中的水果");
}
}
}
//第二个类用来定义一个服务员类
public class Servant implements Runnable{
Plate plate;
public Servant(Plate plate) {
super();
this.plate = plate;
}
@Override
public void run() {
for (int i = 0; i < 6; i++) {
//服务员向果盘中加水果
// System.out.println("服务员第" + i + "次添加果盘中的水果");
plate.addFruit();
// System.out.println(" 服务员第" + i + "添加完完果盘中的水果");
}
}
}
//第三个类用来定义服务员添加水果和客人食用水果的方法
public class Plate {
// 果盘最多有三个水果,服务员一次性添加max个水果
private static final int MAX = 3;
// 果盘当前水果剩余数量
private int count;
// 客人取用水果,一次取用一个
public synchronized void getFruit() {
while (count == 0) {
// 通知服务员
notifyAll();
System.out.println("客人发现果盘中没有水果,客人等待并通知服务员添加水果");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println("客户取用了一个水果,还剩" + count + "个水果");
}
// 服务员添加水果,一次性添加满
public synchronized void addFruit() {
while (count > 0) {
System.out.println("服务员发现果盘还有水果,"
+ "通知客人继续食用,不必添加水果");
try {
wait();// 释放锁,并等待通知继续执行下去
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count = MAX;
System.out.println("服务员把果盘加满,通知客人过来食用");
// 此处表示服务员添加水果,通知客人过来食用
notifyAll();
}
}
//第三个类用来定义主函数测试类
public class TestMain {
public static void main(String[] args) {
//创建一个客人和服务员共同操作的果盘
Plate plate=new Plate();
//创建操作上述果盘的客人
Guest gust=new Guest(plate);
//创建操作上述果盘的服务员
Servant servant=new Servant(plate);
//客人线程
Thread t1=new Thread(gust);
//服务员线程
Thread t2=new Thread(servant);
t1.start();
t2.start();
}
}
测试结果为(仅供参考)【因为客人类运行完毕而服务员类没有运行完毕所以就卡再这里】
解决方案:当你把服务员的运行次数和客人运行次数具有一定的倍数就可以了,比如本工程可以设置服务员的运行次数为两次就可以在客人运行结束后,服务员类也结束。