多线程生产者与消费者模型
生产者与消费者模型,通过Object的wait()以及notifyAll()方法实现以及同步方法实现
相关代码
// 请把代码文本粘贴到下方(请勿用图片代替代码)
class Resource {
private int num = 0;
private boolean flag = true;
// flag为true可以执行加法操作,不可以执行减法操作
// flag为false可以执行减法操作,不可以执行加法操作
public synchronized void add() throws Exception {
if(!this.flag) { // flag为false只能执行减法操作
super.wait(); // 需要等待
}
//Thread.sleep(100);
this.num++;
System.out.println(Thread.currentThread().getName() + "运行, num = " + this.num);
this.flag = false; // 可以进行减法操作
super.notifyAll(); // 唤醒其他线程
}
public synchronized void sub() throws Exception {
if(this.flag) { // flag为true只能进行加法操作,减法操作需要等待
super.wait();
}
// Thread.sleep(100);
this.num--;
System.out.println(Thread.currentThread().getName() + "运行, num = " + this.num);
this.flag = true ; // 可以进行加法操作
super.notifyAll(); // 唤醒其他线程
}
}
class AddThread implements Runnable {
private Resource res;
public AddThread(Resource res) {
this.res = res;
}
@Override
public void run() {
for (int i = 0 ; i < 50 ; i++) {
try {
this.res.add();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class SubThread implements Runnable {
private Resource res;
public SubThread(Resource res) {
this.res = res;
}
@Override
public void run() {
for (int i = 0 ; i < 50 ; i++) {
try {
this.res.sub();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class ThreadDemo {
public static void main(String[] args) {
Resource res = new Resource();
AddThread at = new AddThread(res);
SubThread st = new SubThread(res);
new Thread(at, "加法操作-1").start();
new Thread(at, "加法操作-2").start();
new Thread(st, "减法操作-1").start();
new Thread(st, "减法操作-2").start();
}
}
问题出在,你有两个加线程和两个减线程。然后你有选择用
notifyAll
的方式去唤醒它们。在加线程中使用
notifyAll
的方式唤醒等待的线程,所有的两个减线程都会被唤醒。这两个减线程不会同时运行(因为 synchronized),但是他们会先后运行。减线程被唤醒后,也就是
wait()
返回之后,sub()
没有继续检查flag
的值(注意,wait()
在if (this.flag)
里,不是while
),而是直接修改了num
跟flag
。这样,两个被唤醒的减线程,都会去修改
num
跟flag
。从而num
自减了两次。(被唤醒的第二个减线程运行的时候,
flag
已经变为了true
。但是由于wait()
返回之后没有对flag
的判断,还是去修改了num
。)