肯德基其实就是一个典型的多线程协作
厨师生产汉堡
服务员是一个厨师和消费者共享的资源。
消费者取走汉堡
场景:.厨师先上班,顾客后光顾,店员发现餐台是空的,让厨师生产。当初始生产完毕还没有顾客光临,店员就让初始等待(wait)
此时:店员和餐台是一个共享资源,可以服务多个线程(以厨师为代表的生产者线程和以消费者为代表的生产者线程)。但是不能同时服务多个线程。一个运行一个等待
如何完成多线程的协作??
1.synchronized 确保同一时刻只能有一个线程进入
2.Lock类
wait()方法 :顾客先来厨师没有上班,调用该方法顾客线程进入阻塞同时释放自己持有的锁,一旦厨师来了进入临界区生产产品。
notifyAll()方法:厨师生产完毕,通知客户取走,该方法唤醒所有等待的线程,让所有等待(阻塞)的线程解除阻塞。
public class ProducterTask implements Runnable{
private Clerk clerk;
@Override
public void run() {
try {
for (int i = 1; i <=10 ; i++) {
//调用共享资源的方法生产产品
clerk.setProduct(i);
}
}catch (Exception e){
System.out.println("生产产品失败");
e.printStackTrace();
}
}
public ProducterTask(Clerk clerk){
this.clerk = clerk;
}
}
```java//消费者
public class ConsumerTask implements Runnable {
private Clerk clerk;
@Override
public void run() {
try {
for (int i = 1; i <= 10 ; i++) {
clerk.getProduct();
}
}catch (Exception e){
e.printStackTrace();
}
}
public ConsumerTask(Clerk clerk){
this.clerk = clerk;
}
}
```java//服务员
public class Clerk {
private int product = -1;
/**
* 生产产品:
* 1判断餐台是否为空,为空生产,否则进入阻塞状态 wait
* 2 生产产品
* 3 通知顾客取走
* 参数:就是模拟的产品
*/
public synchronized void setProduct(int product)throws Exception{
synchronized (this){
while (this.product != -1){
//该方法必须配合synchronized一起使用,一旦执行了,线程进入阻塞状态
//释放自己持有共享资源的锁,让其他线程进入
this.wait();
}
//模拟厨师生产产品
this.product = product;
//通知消费者线程,拿走产品
this.notify();
System.out.println("厨师成功生产了" + this.product+"个产品");
}}
public synchronized void getProduct()throws Exception{
synchronized (this){while (this.product == -1){
this.wait();
}
//tmpProduct存储初始生产完毕的产品,执行完毕表示成功拿走产品
int tmpProduct = this.product;
//餐厅置空
this.product = -1;
//唤醒厨师继续生产
this.notify();
System.out.println("顾客成功拿走" + tmpProduct +"个产品");
}}
}
```java//测试类
public class KfcTest {
public static void main(String[] args) {
Clerk clerk = new Clerk();
ProducterTask producterTask = new ProducterTask(clerk);
ConsumerTask consumerTask = new ConsumerTask(clerk);
Thread productThread = new Thread(producterTask, "生产者线程");
Thread ConsumerThread = new Thread(consumerTask, "消费者线程");
productThread.start();
ConsumerThread.start();
}
}