一生產多消費:解決wait條件改變與假死
阿新 • • 發佈:2018-12-17
解決wait()條件改變
判斷執行緒執行條件應該使用while。
若用if判斷,當滿足執行條件時執行緒不能及時響應,而是繼續等待被喚醒,喚醒後將從this.wait()後往下執行,而不會重新判斷是否滿足執行條件,從而發生異常。
解決假死
假死出現的主要原因可能是notify()連續喚醒同類,解決方法是使用notifyAll()喚醒所有等待同一共享資源的全部執行緒。
示例如下:
package entity;
import java.util.List;
import java.util.ArrayList;
public class MyStack {
private List list = new ArrayList();
synchronized public void push() {
try {
while (list.size() == 1) { //使用while判斷
this.wait();
}
list.add("anyString=" + Math.random());
this.notifyAll(); //避免假死
System.out.println("push=" + list.size());
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
}
synchronized public String pop() {
String returnValue = "";
try {
while (list.size() == 0) { //使用while判斷
System.out.println("pop : "
+ Thread.currentThread().getName() + " waiting...");
this.wait();
}
returnValue = "" +list.get(0);
list. remove(0);
this.notifyAll(); //避免假死
System.out.println("pop = " + list.size());
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
return returnValue;
}
}
package service;
import entity.MyStack;
public class P {
private MyStack myStack;
public P(MyStack myStack) {
super();
this.myStack = myStack;
}
public void pushService() {
myStack.push();
}
}
package service;
import entity.MyStack;
public class C {
private MyStack myStack;
public C(MyStack myStack) {
super();
this.myStack = myStack;
}
public void popService() {
System.out.println("pop= " + myStack.pop());
}
}
package thread;
import service.P;
public class PThread extends Thread {
private P p;
public PThread(P p) {
super();
this.p = p;
}
@Override
public void run() {
while(true) {
p.pushService();
}
}
}
package thread;
import service.C;
public class CThread extends Thread {
private C c;
public CThread(C c) {
super();
this.c = c;
}
@Override
public void run() {
while(true) {
c.popService();
}
}
}
package test;
import entity.MyStack;
import service.C;
import service.P;
import thread.CThread;
import thread.PThread;
public class Run {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyStack myStack = new MyStack();
P p = new P(myStack);
C c1 = new C(myStack);
C c2 = new C(myStack);
C c3 = new C(myStack);
C c4 = new C(myStack);
C c5 = new C(myStack);
PThread pThread = new PThread(p);
pThread.start();
CThread[] cThread = new CThread[5];
cThread[0] = new CThread(c1);
cThread[1] = new CThread(c2);
cThread[2] = new CThread(c3);
cThread[3] = new CThread(c4);
cThread[4] = new CThread(c5);
cThread[0].start();
cThread[1].start();
cThread[2].start();
cThread[3].start();
cThread[4].start();
}
}