分析假死的原因:
首先我们每次只生产一个数据,然后消费者进行消费,
public class Value { public static String value = "";//这个值作为生产消费的容器 }
生产者端代码:
private String lock; public Producer (String lock) { super(); this.lock = lock; } public void setValue() { try { synchronized (lock) { while (!"".equals(Value.value)) { System.out.println("生產者:"+Thread.currentThread().getName()+"等待"); lock.wait(); } System.out.println("生產者:"+Thread.currentThread().getName()+"开始工作了"); String value = "Producer"; System.out.println("set value :"+value); Value.value = value; lock.notify(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
消费者端
private String lock; public Consumer(String lock) { this.lock = lock; } public void getValue() { try { synchronized (lock) { if ("".equals(Value.value)) { System.out.println("消费者:"+Thread.currentThread().getName()+"等待"); lock.wait(); } System.out.println("消费者:"+Thread.currentThread().getName()+"开始消费了"); System.out.println("get value :"+Value.value ); Value.value = ""; lock.notify(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
public class MyThread1 extends Thread {
private Producer p;
public MyThread1(Producer p) {
this.p = p;
}
@Override
public void run() {
while(true){
p.setValue();//此线程不停的生产
}
}
package com.demo.thread;
public class MyThread2 extends Thread{
private Consumer c;
public MyThread2(Consumer c) {
this.c = c;
}
@Override
public void run() {
while (true) {
c.getValue();//此线程不听的消费
}
}
}
测试:
String lock = new String("lock"); Producer p = new Producer (lock); Consumer c = new Consumer (lock); MyThread1[] t1 = new MyThread1[2]; MyThread2 [] t2 = new MyThread2[2]; for(int i = 0 ;i<2;i++){ t1[i] = new MyThread1(p); t1[i].setName("生产者:"+(i+1)); t2[i] = new MyThread2(c); t2[i].setName("消费者:"+(i+1)); t1[i].start(); t2[i].start(); } Thread.sleep(3000); Thread[] tArr = new Thread [Thread.currentThread().getThreadGroup().activeCount()]; Thread.currentThread().getThreadGroup().enumerate(tArr); for(int i = 0 ;i<tArr.length;i++){ System.out.println(tArr[i].getName()+"\t"+tArr[i].getState()); }
截取控制台代码部分代码:
分析:因为notify每次只唤醒一个线程,因此并不确定他唤醒的是哪一个线程,所以消费1唤醒的是消费者2,此时刚好没有数据被生产,消费者2也进入等待,并唤醒生产者2,生产者2生产完数据之后进入wait同时唤醒线程,此时唤醒的是生产者1 ,因为数据不为空,因此两生产者都进入等待状态,此时四个线程全部wait,即假死状态,结果如控制台所示.
解决方式:这里每次执行完毕之后应该唤醒所有线程即可.
生產者:生产者:2开始工作了 set value :Producer 消费者:消费者:1开始消费了 get value :Producer 消费者:消费者:1等待 生產者:生产者:2开始工作了 set value :Producer 生產者:生产者:2等待 生產者:生产者:1等待 消费者:消费者:2开始消费了 get value :Producer 消费者:消费者:2等待 生產者:生产者:2开始工作了 set value :Producer 生產者:生产者:2等待 生產者:生产者:1等待 消费者:消费者:1开始消费了 get value :Producer 消费者:消费者:1等待//消费者1等待,唤醒消费者2 消费者:消费者:2开始消费了 get value : 消费者:消费者:2等待//消费者2唤醒生产者2 生產者:生产者:2开始工作了 set value :Producer 生產者:生产者:2等待//从这里开始,生产者2唤醒1,两者最后都进入wait. 生產者:生产者:1等待 main RUNNABLE 生产者:1 WAITING 消费者:1 WAITING 生产者:2 WAITING 消费者:2 WAITING