進程同步問題——生產者、消費者問題
生產者、消費者問題是操作系統中個著名的進程同步問題。一般是指: 有一羣生產者進程在生產產品,並將此產品提供給消費者進程去消費。爲使生產者進程和消費者進程能併發執行,在它們之間設置一個緩衝區, 生產者進程可將它所產的產品放入一個緩衝區中,消費者進程可從一個緩衝區取得一個產品消費。儘管所有的生產者進程和消費者進程都是以異步的方式運行的,但它們之間必須保持同步,即不允許消費者進程到一個空緩衝區去取產品,也不允許生產者進程向一個已裝有消息、 但尚未取走產品的滿緩衝區投放產品。這裏將“進程”換成“線程”,問題仍然成立。下面要做由事情就是用線程來模擬這一過程。
在這裏設計一個公共類,信號量和共享資源都以靜態成員變量的形式存於該對象中。在創建線程對象時,將這個公共對象牀底進去,作爲線程對象的私有數據。這樣無論哪個線程對象,訪問的都是同一個信號量和共享資源。
公共類的實現:
public class Common { //公共線程類
private int production[];
private int count; //實際產品數目
private int BUFFER_SIZE=6; //緩衝區大小
public Common(){
production=new int[BUFFER_SIZE];
count=0;
}
//從緩衝區取數據
public synchronized int get(){
int result;
//循環檢測緩衝區是否可用
while (count<=0) {
try {
wait(); //等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result=production[--count];
notifyAll();
return result;
}
//向緩衝區寫數據
public synchronized void put(int newProduct){
//循環檢測緩衝區是否可用
while (count>=BUFFER_SIZE){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
production[count++]=newProduct;
notifyAll();
}
}
消費者線程:
public class Consumer extends Thread {
private Common common;
public Consumer(Common thisCommon){
common=thisCommon;
}
public void run(){
int i,production;
for(i=1;i<=20;i++){
production=common.get();
System.out.println("得到的數據是:"+production);
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
生產者線程:
public class Producer extends Thread {
private Common common;
public Producer(Common thisCommon){
common=thisCommon;
}
public synchronized void run(){
for(int i=1;i<=10;i++){
common.put(i);
System.out.println("生產的數據是:"+i);
try{
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
主線程:
public class Producer_Consumer {
public static void main(String[] args){
Common common=new Common();
//兩個生產者
Producer producer1=new Producer(common);
Producer producer2=new Producer(common);
//一個消費者
Consumer consumer=new Consumer(common);
producer1.start();
producer2.start();
consumer.start();
}
}
運行結果截圖: