分析假死的緣由:java
首先咱們每次只生產一個數據,而後消費者進行消費,ide
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(); } }消費者端this
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()); }
截取控制檯代碼部分代碼:code
分析:由於notify每次只喚醒一個線程,所以並不肯定他喚醒的是哪個線程,因此消費1喚醒的是消費者2,此時恰好沒有數據被生產,消費者2也進入等待,並喚醒生產者2,生產者2生產完數據以後進入wait同時喚醒線程,此時喚醒的是生產者1 ,由於數據不爲空,所以兩生產者都進入等待狀態,此時四個線程所有wait,即假死狀態,結果如控制檯所示.get
解決方式:這裏每次執行完畢以後應該喚醒全部線程便可.it
生產者:生產者: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