經典問題-生產者和消費者問題

生產者和消費者是一個多線程同步的經典案例,該問題描述了兩個共享固定大小緩衝區的線程,即所謂的「生產者」和「消費者」,顧名思義,生產者指的就是生產必定的數據量到緩衝區,而消費者就是從緩衝區取走必定的數據。java

生產者和消費者問題要解決一個死鎖問題,就是當緩衝區已經滿的時候,生產者佔着它等待消費者來取走數據,而消費者則等着生產者讓出緩衝區的權利好取走數據,因而就相互等待,從而形成死鎖。多線程

本程序只有一個生產者和一個消費者,使用wait和notify(nitify)方法來避免死鎖問題,這裏得提一下wait和notify(notifyAll)方法,線程中的wait、notify以及notifyAll方法:都是定義在Object類中的final方法,即全部的類都默認擁有這3個方法,但只用於synchronized關鍵字做用的範圍內,而且是搭配着一塊兒使用;wait方法是通知當前線程等待並釋放對象鎖;notify方法是通知等待此對象鎖的一個線程從新得到線程鎖;notifyAll是喚醒全部等待此對象鎖的線程。this

public class ProducerConsumer {
	
	public static void main(String[] args) {
		
		SyncStack myStack = new SyncStack(6);
		
		Producer producer = new Producer(myStack);
		Consumer consumer = new Consumer(myStack);
		
		Thread t1 = new Thread(producer);
		Thread t2 = new Thread(consumer);
		
		t1.start();
		t2.start();
		
	}
}

class Bread {
	
	private int id;
	
	Bread(int id) {
		this.id = id;
	}
	
	public int getId() {
		return id;
	}
}


class SyncStack {
	
	private int size;
	private int index = 0;
	private Bread[] myBread;
	
	SyncStack(int size) {
		this.size = size;
		myBread = new Bread[size];
	}
	
	public synchronized void put(Bread bread) {
		while (index == size) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		myBread[index] = bread;
		++index;
		System.out.println("Producer puts bread: " + bread.getId());
		this.notify();
	}
	
	public synchronized Bread remove() {
		while (index == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		--index;
		System.out.println("Consumer removers bread: " + myBread[index].getId());
		this.notify();
		return myBread[index];
	}	
	
}

class Producer extends Thread {
	
	private SyncStack myStack;
	
	Producer(SyncStack myStack) {
		this.myStack = myStack;
	}
	
	public void run() {
		
		for (int i = 1; i <= 20; ++i) {
			myStack.put(new Bread(i));
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}


class Consumer extends Thread {
	
	private SyncStack myStack;
	
	Consumer(SyncStack myStack) {
		this.myStack = myStack;
	}
	
	public void run() {	
		for (int i = 1; i <= 20; ++i) {	
			Bread bread = myStack.remove();
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
相關文章
相關標籤/搜索