一个卖面的面馆,有一个做面的厨师和一个吃面的食客,需要保证,厨师做一碗面,食客吃一碗面,不能一次性多做几碗面,更不能没有面的时候吃面;按照上述操作,进行十轮做面吃面的操作
三组等待与唤醒
这里是使用第一组
synchronized(锁) wait(线程等待阻塞)notifyAll(唤醒全部线程)
做面方法代码如下 :
public void makeNoodles() {
synchronized (this) {
//如果食客没吃完
while (number != 0) {
//等待食客吃完
try {
System.out.println(Thread.currentThread().getName() + "食客没有吃完,弃锁等待中...");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//食客已经吃完,线程被唤醒,开始做面
if (number <= 0) {
number++;
System.out.println(Thread.currentThread().getName() + "做" + number + "碗面 ----> number=" + number);
}
//唤醒食客吃面
if (number > 0) {
this.notifyAll();
}
}
}
吃面方法代码如下 :
public void eatNoodles() {
synchronized (this) {
//如果厨师没做好
while (number <= 0) {
try {
System.out.println(Thread.currentThread().getName() + "没有面条吃,弃锁等待中...");
this.wait();//等待厨师做面
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//厨师已经吃好,线程被唤醒,开始吃面
if (number > 0) {
System.out.println(Thread.currentThread().getName() + "吃" + number + "碗面 ----> number=" + --number);
}
//吃完唤醒厨师做面
if (number <= 0) {
this.notifyAll();
}
}
}
多个线程调用做面方法和吃面方法
CountDownLatch countDownLatch = new CountDownLatch(40);
new Thread(() -> {
for (int i = 0; i < 10; i++) {
makeNoodles();
countDownLatch.countDown();
}
}, "厨师01").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
eatNoodles();
countDownLatch.countDown();
}
}, "食客01").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
makeNoodles();
countDownLatch.countDown();
}
}, "厨师002").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
eatNoodles();
countDownLatch.countDown();
}
}, "食客002").start();
countDownLatch.await();
打印执行结果:经常出现厨师(食客)做(吃)完面再次拿到锁又弃锁等待的情况,是因为synchronized 变成了偏向锁,对象的对象头中保存中偏向的线程id
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客01 没有面条吃,弃锁等待中...
食客002 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师01 看食客没有吃完,弃锁等待中...
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
食客01 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
厨师01 看食客没有吃完,弃锁等待中...
食客01吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师01做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
厨师002 看食客没有吃完,弃锁等待中...
食客002吃1碗面 ----> number=0
食客002 没有面条吃,弃锁等待中...
厨师002做1碗面 ----> number=1
食客002吃1碗面 ----> number=0