题目背景是一个厨师和一个吃货
代码展示:
1.厨师:
package a0416;
public class Cook extends Thread{
@Override
public void run() {
while(true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
if(Desk.foodflag==0){
System.out.println("厨师做了第"+(11-Desk.count)+"碗面条");
Desk.foodflag=1;
Desk.lock.notifyAll();
}else{
try {
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
}
2.桌子:
package a0416;
public class Desk {
public static int foodflag=0;
public static int count=10;
public static Object lock=new Object();
}
3.吃货:
package a0416;
public class Food extends Thread{
@Override
public void run() {
/*
*1.循环
*2.同步代码块
*3.判断共享数据到了末尾
*4.共享数据没有到末尾 */
while(true){
synchronized (Desk.lock){
if(Desk.count==0){
break;
}else{
/*先判断桌子上面有没有面条
* 没有等面条,有就吃面条
* 吃完唤醒厨师继续做面条
* 吃的总数减去1
* 改变桌子上面条的状态*/
if(Desk.foodflag==0){
//等待面条
try {
Desk.lock.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}else{
Desk.count--;
System.out.println("吃货还能吃"+Desk.count+"碗面条");
Desk.lock.notifyAll();
Desk.foodflag=0;
}
}
}
}
}
}
5.测试:
package a0416;
public class Test1 {
public static void main(String[] args) {
Cook c=new Cook();
Food f=new Food();
c.setName("厨师");
f.setName("吃货");
c.start();
f.start();
}
}
理解:
我自己理解的时候有个地方一直没弄懂就是吃货里面的最后两行代码这是我一开始的疑惑:
Desk.lock.notifyAll();
Desk.foodflag = 0;
这行代码中的 Desk.foodflag = 0; 将在什么时候进行呢?当Desk.lock.notifyAll(); 释放了锁如果Food没有抢到那岂不是不会执行Desk.foodflag = 0;
解释:我一直以为执行Desk.lock.notifyAll();时就会释放锁但其实不是的,notifyAll和notifywait是有很大的区别的,notifyAll执行后并不会立马释放锁他是要等锁的语句块执行完以后才会释放锁,notifyAll只是唤醒了同一个锁的在等待的线程告诉他准被抢了,但还没有释放锁还进不去;而notifywait执行后就会立马释放锁;所以在这里还是有一些区别的。
还有一点就是这个代码这么写的好处是,当我的吃货线程执行一次执行完后,如果再一次抢到了根据代码他就会等待并释放锁拿这一次没有线程和厨师线程抢了就一定时厨师线程抢到了cpu行使权。