题目要求: | 现在有一个果篮,里面可以放置很多苹果,编码者作为一个苹果的生产者,负责向这个果篮中放置苹果 | 提示:通过控制台输入的数字,决定每次放置到果篮的苹果数。 | 现在有3个孩子作为消费者,负责从这个果篮中每次去拿一个苹果,然后吃掉 | 孩子A:吃苹果需要3秒钟 | 孩子B:吃苹果需要2秒钟 | 孩子C:吃苹果需要4秒钟 | 现在需要设计若干个类,并充分运用wait\sleep\notifyAll\synchronized满足下述要求 | ①需要设计3个线程代表三个孩子去同步从果篮中获取苹果 | ②每个孩子需要等待生产者的通知,当生产者(编码者)放置苹果的时候,才会去果篮中拿苹果 | ③每个孩子拿完一个苹果之后,会花一定的时间来吃苹果,然后继续从果篮中获得苹果,如果果篮为空,进入等待生产者通知状态 | ④生产者在向果篮放置苹果的时候,根据控制台输入的数字决定放置苹果的个数,并通知所有线程可以去拿苹果 | 解析: 对于生产者消费者问题,要理清楚哪些资源是被并发访问的,然后在此资源上加上适当的锁就可以了。 import java.util.Scanner;
/**
* 果篮类
* 1.果篮类是一个公共区域,生产者可以将苹果放入果篮,消费者则可以从果篮中取走苹果;
* 2.要解决的问题是如何保证此果篮被多个生产者或者多个消费者并发访问时的数据的完整性;
* 3.这里解决的方法是使用同步锁机制;
*
* @author guocunlei
*
*/
public class FruitBasket {
private static int appleNum = 0;
public int getAppleNum() {
return appleNum;
}
/**
* 生产者生产苹果
*
* @throws InterruptedException
*/
public synchronized void produce() throws InterruptedException {
// 如果苹果的数量不为0,说明果篮里还不为空,就不必生产
while (appleNum != 0) {
System.out.println("果篮中的苹果数量为" + appleNum);
this.wait();
}
// 如果为空就提醒生产者生产
@SuppressWarnings("resource")
Scanner sc = new Scanner(System.in);
System.out.println("输入生产的苹果数:");
appleNum = sc.nextInt();
System.out.println("生产者已生产" + appleNum + "个苹果");
// 此时唤醒所有等待的线程
notifyAll();
}
/**
* 消费者消费苹果
*/
public synchronized void consume(String customerName) throws InterruptedException {
// 如果苹果数量为0,就进入等待状态
while (appleNum == 0) {
System.out.println("果篮中的苹果数量为" + appleNum + "," + customerName + "正在等待生产者通知...");
this.wait();
}
// 如果不为0,就消费苹果
System.out.println(customerName + "正在尝试获取苹果...");
appleNum--;
System.out.println(customerName + "获取苹果成功!此时果篮中的苹果数为" + appleNum);
notifyAll();
}
}
/*
* 生产者类:此生产者主要负责生产苹果
*/
public class ProduceThread extends Thread {
private FruitBasket fb;
public ProduceThread(FruitBasket fruitBasket) {
this.fb = fruitBasket;
}
public void run() {
try {
//进行生产,并将生产的产品放进篮子
fb.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/*
* 消费者类
*/
public class CustomerThread extends Thread {
private FruitBasket fb;
// 消费者的名称
private String customerName;
// 消费者消费产品所用的时间
private long millisecond;
public CustomerThread(FruitBasket fruitBasket, String customerName, long millisecond) {
this.millisecond = millisecond;
this.customerName = customerName;
this.fb = fruitBasket;
}
@Override
public void run() {
try {
while (true) {
// 从果篮中拿出产品(消费产品)
fb.consume(customerName);
Thread.sleep(millisecond);
System.out.println(customerName + "吃完了苹果耗时" + millisecond / 1000 + "秒");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Main {
public static void main(String[] args) {
FruitBasket fruitBasket = new FruitBasket();
//生产者
ProduceThread produceThread = new ProduceThread(fruitBasket);
//三个消费者
CustomerThread customerThread1 = new CustomerThread(fruitBasket, "孩子A", 3000);
CustomerThread customerThread2 = new CustomerThread(fruitBasket, "孩子B", 2000);
CustomerThread customerThread3 = new CustomerThread(fruitBasket, "孩子C", 4000);
//开启线程
produceThread.start();
customerThread1.start();
customerThread2.start();
customerThread3.start();
}
}
|