Java訊號量實現程式同步問題:水果蘋果香蕉問題
程式同步控制
1,問題描述
問題描述:編寫Windows下父親兒子女兒放取水果程式同步的演示程式。(問題描述:桌上有一空盤,最多允許存放一個水果。爸爸可向盤中放一個蘋果或放一個桔子,兒子專等吃盤中的桔子,女兒專等吃蘋果。 試用P、V操作實現爸爸、兒子、女兒三個併發程式的同步。提示:設定一個訊號量表示可否向盤中放水果,一個訊號量表示可否取桔子,一個訊號量表示可否取蘋果。
在解決程式同步問題中,有一種方式叫做訊號量機制,即通過訊號量來將不同的程式進行控制和使用,使其避免出現死鎖現象。
在本題中,父親放水果,兒子拿蘋果,女兒拿香蕉都是不同的程式,可以在不同的時間允許和操作。但如何進行,這就是要解決的問題。
2,Java中的訊號量是java.util.concurrent.Semaphore
函式實現的。
訊號量
Semaphore
通過使用計數器counter
來控制對共享資源的訪問。如果計數器大於零,則允許訪問。如果為零,則拒絕訪問。計數器對共享資源的訪問許可進行計數。因此,要訪問資源,執行緒必須要從訊號量得到許可。
Semaphore 的建構函式有兩種:
Semaphore(int num)
Semaphore(int num, boolean how)
其中的
num
,表示指定初始的許可計數。因此,它也就指定了一次可以同時訪問共享資源的執行緒數。如果是1
,那麼同時只能有一個執行緒可以訪問該資源。預設情況下,所有等待的執行緒都以未定義的順序被授予許可
。通過設定how為true
,可以確保等待執行緒按其請求訪問的順序被授予許可
。
該函式會使用到的方法有,Semaphore.acquire()
,獲取訊號量的控制權的鎖,類比於P
操作,Semaphore.release()
,釋放訊號量的控制鎖,類比於V
操作。
關於訊號量的部落格:Java中的訊號量Semaphore
下面開始使用,這本題中設定,3個訊號量:
static Semaphore empty = new Semaphore(1,true);//資源區是否為空
static Semaphore apple = new Semaphore(0,true);//資源區蘋果訊號
static Semaphore banana = new Semaphore(0,true);//資源區香蕉訊號
第一個empty
訊號量表示,盤中是否有水果,也是對於父親的放水果的操作的控制。apple
訊號量,用於兒子的拿蘋果的操作,banana
用於女兒拿香蕉的操作。
3,父親的相關程式碼:
//父親的程式
Thread father = new Thread(new Runnable() {
public void run() {
while (true) {
try {
empty.acquire();//申請操作許可權相當於wait(S)
int random = Math.random() >= 0.5 ? 1 : 0;
if (random == 1) {
System.out.println("父親放入了一個蘋果");
Thread.sleep(1000);//休眠表示放入的過程
apple.release();//喚醒兒子的訪問
} else {
System.out.println("父親放入了一個香蕉");
Thread.sleep(1000);
banana.release();//喚醒女兒的訪問
}
} catch (InterruptedException e) {
System.out.println("父親獲取資源失敗!");
e.printStackTrace();
}
}
}
});
父親先獲取操作權,然後進行放水果的操作。放好以後,根據放的水果的種類,喚醒對於的程式。
4,女兒和兒子的程式碼:
//女兒的程式
Thread daughter = new Thread(new Runnable() {
public void run() {
while (true){
try {
banana.acquire();//獲取banana的資源
System.out.println("女兒取走了一個香蕉!");
Thread.sleep(1000);//取走的過程
empty.release();//釋放父親放的訊號量
} catch (InterruptedException e) {
System.out.println("女兒獲取資源失敗!");
e.printStackTrace();
}
}
}
});
//兒子的程式
Thread son = new Thread(new Runnable() {
public void run() {
while (true){
try {
apple.acquire();//兒子獲取資源
System.out.println("兒子取走了一個蘋果!");
Thread.sleep(1000);//取的過程
empty.release();//釋放資源
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("兒子獲取資源失敗!");
}
}
}
});
兒子或女兒取了水果以後,由於只能存放一個,因此直接將控制權返回給父親,即喚醒父親的程式。
5,完整程式碼例項:
import java.util.concurrent.Semaphore;
/**
* 訊號量Semaphore 通過使用計數器counter來控制對共享資源的訪問。
* 如果計數器大於零,則允許訪問。如果為零,則拒絕訪問。
* 計數器對共享資源的訪問許可進行計數。因此,要訪問資源,執行緒必須要從訊號量得到許可。
*/
public class ProcessTest {
static Semaphore empty = new Semaphore(1,true);//資源區是否為空
static Semaphore apple = new Semaphore(0,true);//資源區蘋果訊號
static Semaphore banana = new Semaphore(0,true);//資源區香蕉訊號
public static void main(String[] args) {
//父親的程式
Thread father = new Thread(new Runnable() {
public void run() {
while (true) {
try {
empty.acquire();//申請操作許可權相當於wait(S)
int random = Math.random() >= 0.5 ? 1 : 0;
if (random == 1) {
System.out.println("父親放入了一個蘋果");
Thread.sleep(1000);//休眠表示放入的過程
apple.release();//喚醒兒子的訪問
} else {
System.out.println("父親放入了一個香蕉");
Thread.sleep(1000);
banana.release();//喚醒女兒的訪問
}
} catch (InterruptedException e) {
System.out.println("父親獲取資源失敗!");
e.printStackTrace();
}
}
}
});
//女兒的程式
Thread daughter = new Thread(new Runnable() {
public void run() {
while (true){
try {
banana.acquire();//獲取banana的資源
System.out.println("女兒取走了一個香蕉!");
Thread.sleep(1000);//取走的過程
empty.release();//釋放父親放的訊號量
} catch (InterruptedException e) {
System.out.println("女兒獲取資源失敗!");
e.printStackTrace();
}
}
}
});
Thread son = new Thread(new Runnable() {
public void run() {
while (true){
try {
apple.acquire();//兒子獲取資源
System.out.println("兒子取走了一個蘋果!");
Thread.sleep(1000);//取的過程
empty.release();//釋放資源
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("兒子獲取資源失敗!");
}
}
}
});
father.setName("父親");
daughter.setName("女兒");
son.setName("兒子");
father.start();
daughter.start();
son.start();
}
}
相關文章
- 無名訊號量實現哲學家問題
- 有名訊號量實現消費者生產者問題
- 使用訊號量Semaphore實現沒有飢餓問題的鎖
- 有名訊號量實現讀者-寫者問題(讀者優先)
- 無名訊號量實現相關程式同步
- 面試必問:訊號量與生產者消費者問題!面試
- 關於oracle資料庫訊號量的問題Oracle資料庫
- 經典n皇后問題java程式碼實現Java
- 作業系統綜合題之“用記錄型訊號量機制的wait操作和signal操作寫出三個程序的同步程式碼(水果進框問題-程式碼補充)”作業系統AI
- 或為硬體問題 蘋果iPhone SE藍芽訊號弱蘋果iPhone藍芽
- 漢羅塔問題 java實現Java
- Java實現-揹包問題IJava
- Java實現-揹包問題IIJava
- Java實現-揹包問題VIJava
- 讀寫者問題-java實現Java
- Java服務.問題排查.問題復現Java
- synchronized同步程式+生產者消費者模式(訊號燈)解除可能出現的資源問題synchronized模式
- 記一個openwrt reboot非同步訊號處理死鎖問題boot非同步
- Java同步問題面試參考指南Java面試
- 測試CMS同步問題測試CMS同步問題
- jive 同步問題
- Linux程式設計:程式同步問題之哲學家就餐問題Linux程式設計
- 【計題04組01號】Java面試問答題Java面試
- 微信公眾號傳送模板訊息,出現亂碼問題---字元中文編碼問題字元
- 利用訊號量semaphore實現兩個程式讀寫同步 Linux CLinux
- 無題號 分配問題 題解
- 二分搜尋演算法-吃香蕉問題演算法
- java實現pv操作 -------哲學家問題Java
- ogg 同步問題
- 登陸sqlplus出現問號的問題SQL
- 訊號量實現生產者消費者(程式碼邏輯有問題,不適合多個消費者,不常用)
- java 問題Java
- MySQL行號問題MySql
- 您說的這個功能實現不是問題,問題是實現不了~~
- 由“香蕉”引出的字串匹配演算法的問題字串匹配演算法
- java實現生產者消費者問題Java
- JAVA實現附近範圍內公交定位問題Java
- java中實現報表樣式的問題Java