分析假死的原因:
首先我们每次只生产一个数据,然后消费者进行消费,
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