代码实例(参考代码:TreadCom3.java)
/*多生产者多消费者
生产一个馒头就消费一个馒头
两个线程生产馒头,两个线程消费馒头
*/
class Resource3 { //公共资源
private String name;
private int count = 0;
private boolean flag = false;
private void setName(String name) {
this.name = name;
count++;
}
//生产方法
public synchronized void producer() {
// if(flag) //有馒头就等待
while (flag) { //备注问题1
try {
this.wait();
} catch (InterruptedException e) {
}
}
setName("馒头");
System.out.println(name + "...生产者..." + count);
notifyAll();
flag = true;
}
//消费方法
public synchronized void consumer() {
//if(!flag) //没有馒头就等待
while (!flag) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
System.out.println(name + "...消费者..." + count);
notifyAll(); //备注问题2
flag = false;
}
}
//生产线程
class TreadPro implements Runnable {
private Resource3 r;
TreadPro(Resource3 r) {
this.r = r;
}
//生产方法
public void run() {
while (true) {
r.producer();
}
}
}
//消费线程
class TreadCon implements Runnable {
private Resource3 r;
TreadCon(Resource3 r) {
this.r = r;
}
//消费方法
public void run() {
while (true) {
r.consumer();
}
}
}
public class TreadCom3 {
public static void main(String[] args) {
//同一资源
Resource3 r = new Resource3();
//不同任务
TreadPro p = new TreadPro(r);
TreadCon c = new TreadCon(r);
//多个线程,两个生产,两个消费
Thread t0 = new Thread(p);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
Thread t3 = new Thread(c);
t0.start();
t1.start();
t2.start();
t3.start();
}
}
输出结果:
。
。
。
馒头...生产者...44187
馒头...消费者...44187
馒头...生产者...44188
馒头...消费者...44188
馒头...生产者...44189
馒头...消费者...44189
。
。
。
问题备注说明:
1、问题:用if只判断一次,如果线程0和线程1都在线程池,然后线程0被唤醒执行之后,接着又唤醒了线程1,这样就造成了生产多个馒头的情况。
解决办法:需要在线程1醒来之后在去判断一下标志位(while)。
2、问题:用while时,如果出现消费的线程都在线程池内,并生产线程0在线程内,线程1执行完后唤醒的是线程0那么线程0也会立即进入到线程池中,所以,导致所有线程都在线程池中,造成死锁。
解决办法:进行所有线程唤醒动作notifyAll();。