生产者,消费者。
多生产者,多消费者的问题。
if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行!
notify:只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
notifyAll解决了本方线程一定会唤醒对方线程的问题。
package demo.thread;
//烤鸭类
class RoastDuck {
private String name;
private int count = 0;
private boolean flag = false;
synchronized void set(String name) {
while (flag == true) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name;
count++;
System.out.println(Thread.currentThread().getName() + "...生产者..." + this.name + count);
flag = true;
notifyAll();
}
/* 如果while改为if :
t0进来造鸭1,然后wait。
t1进来wait。
t2进来吃鸭1,吃完wait,并唤醒t0。
t2进来wait
t0醒来造鸭2,然后wait,并唤醒t1
t1直接造鸭3 !!! (烤鸭二还没吃呢)
如果notify改为notifyAll :
t0进来造鸭1,然后wait。
t1进来wait。
t2进来吃鸭1,吃完wait,并唤醒t0。
t2进来wait
t0醒来造鸭2,然后wait,并唤醒t1
t1直接wait (全wait了)
//毕向东JavaSE基础视频14 27-多线程(线程间通信-多生产者多消费者问题解决) 8min处
*/
synchronized void eat() {
while (flag == false) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "...消费者........" + this.name + count);
flag = false;
notifyAll();
}
}
//生产者
class Producer implements Runnable {
private RoastDuck r;
Producer(RoastDuck r) {
this.r = r;
}
public void run() {
while (true) {
r.set("烤鸭");
}
}
}
//消费者
class Consumer implements Runnable {
private RoastDuck r;
Consumer(RoastDuck r) {
this.r = r;
}
public void run() {
while (true) {
r.eat();
}
}
}
class RoastDuckTest {
public static void main(String[] args) {
RoastDuck r = new RoastDuck();
Producer pro = new Producer(r);
Consumer con = new Consumer(r);
Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
本文通过烤鸭类的实例详细解析了多生产者多消费者问题中的线程间通信机制,对比了if判断与while判断的区别,以及notify与notifyAll在避免死锁和正确唤醒线程方面的作用。

被折叠的 条评论
为什么被折叠?



