1. 程式人生 > >一生產多消費:解決wait條件改變與假死

一生產多消費:解決wait條件改變與假死

解決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();
	}
}