哲學(xué)家就餐問(wèn)題中的JAVA多線程學(xué)習(xí)
問(wèn)題描述:一圓桌前坐著5位哲學(xué)家,兩個(gè)人中間有一只筷子,桌子中央有面條。哲學(xué)家思考問(wèn)題,當(dāng)餓了的時(shí)候拿起左右兩只筷子吃飯,必須拿到兩只筷子才能吃飯。上述問(wèn)題會(huì)產(chǎn)生死鎖的情況,當(dāng)5個(gè)哲學(xué)家都拿起自己右手邊的筷子,準(zhǔn)備拿左手邊的筷子時(shí)產(chǎn)生死鎖現(xiàn)象。
解決辦法:
1、添加一個(gè)服務(wù)生,只有當(dāng)經(jīng)過(guò)服務(wù)生同意之后才能拿筷子,服務(wù)生負(fù)責(zé)避免死鎖發(fā)生。
2、每個(gè)哲學(xué)家必須確定自己左右手的筷子都可用的時(shí)候,才能同時(shí)拿起兩只筷子進(jìn)餐,吃完之后同時(shí)放下兩只筷子。
3、規(guī)定每個(gè)哲學(xué)家拿筷子時(shí)必須拿序號(hào)小的那只,這樣最后一位未拿到筷子的哲學(xué)家只剩下序號(hào)大的那只筷子,不能拿起,剩下的這只筷子就可以被其他哲學(xué)家使用,避免了死鎖。這種情況不能很好的利用資源。
代碼實(shí)現(xiàn):實(shí)現(xiàn)第2種方案
package cn.edu.sdust.Philosopher;
/*每個(gè)哲學(xué)家相當(dāng)于一個(gè)線程*/
class Philosopher extends Thread{
private String name;
private Fork fork;
public Philosopher(String name,Fork fork){
super(name);
this.name=name;
this.fork=fork;
}
public void run(){
while(true){
thinking();
fork.takeFork();
eating();
fork.putFork();
}
}
public void eating(){
System.out.println("I am Eating:"+name);
try {
sleep(1000);//模擬吃飯,占用一段時(shí)間資源
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void thinking(){
System.out.println("I am Thinking:"+name);
try {
sleep(1000);//模擬思考
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Fork{
/*5只筷子,初始為都未被用*/
private boolean[] used={false,false,false,false,false,false};
/*只有當(dāng)左右手的筷子都未被使用時(shí),才允許獲取筷子,且必須同時(shí)獲取左右手筷子*/
public synchronized void takeFork(){
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
while(used[i]||used[(i+1)%5]){
try {
wait();//如果左右手有一只正被使用,等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
used[i ]= true;
used[(i+1)%5]=true;
}
/*必須同時(shí)釋放左右手的筷子*/
public synchronized void putFork(){
String name = Thread.currentThread().getName();
int i = Integer.parseInt(name);
used[i ]= false;
used[(i+1)%5]=false;
notifyAll();//喚醒其他線程
}
}
//測(cè)試
public class ThreadTest {
public static void main(String []args){
Fork fork = new Fork();
new Philosopher("0",fork).start();
new Philosopher("1",fork).start();
new Philosopher("2",fork).start();
new Philosopher("3",fork).start();
new Philosopher("4",fork).start();
}
}
運(yùn)行結(jié)果:
I am Thinking:0
I am Thinking:2
I am Thinking:3
I am Thinking:1
I am Thinking:4
I am Eating:0
I am Eating:2
I am Thinking:0
I am Eating:4
I am Thinking:2
I am Eating:1
I am Thinking:4
I am Eating:3
I am Thinking:1
I am Eating:0
I am Thinking:3
I am Eating:2
I am Thinking:0
I am Eating:4
I am Thinking:2
分析:上述解決方案解決了死鎖問(wèn)題。可以看到最多只能有兩條相鄰的eating結(jié)果,因?yàn)槊總€(gè)時(shí)刻最多能夠滿足兩個(gè)人同時(shí)進(jìn)餐,且兩人座位不相鄰。
相關(guān)文章
Spring Boot集成Swagger接口分類(lèi)與各元素排序問(wèn)題
這篇文章主要介紹了Spring Boot集成Swagger接口分類(lèi)與各元素排序問(wèn)題,首先我們需要對(duì)Swagger中的接口也就是以Controller 層作為第一級(jí)梯度進(jìn)行組織的,Controller在我們實(shí)際開(kāi)發(fā)中,與其他具體接口之間是存在一對(duì)多的關(guān)系,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10
JavaSE API實(shí)現(xiàn)生成隨機(jī)數(shù)的2種方法(Random類(lèi)和Math類(lèi)的Random方法)
本文主要介紹了JavaSE API實(shí)現(xiàn)生成隨機(jī)數(shù)的2種方法,主要包括Random類(lèi)和Math類(lèi)的random方法都可以用來(lái)生成隨機(jī)數(shù),具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
MyBatis源碼解析之Transaction事務(wù)模塊
這篇文章主要介紹了MyBatis源碼解析之Transaction事務(wù)模塊,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
Spring?Retry?實(shí)現(xiàn)樂(lè)觀鎖重試實(shí)踐記錄
本文介紹了在秒殺商品SKU表中使用樂(lè)觀鎖和MybatisPlus配置樂(lè)觀鎖的方法,并分析了測(cè)試環(huán)境和生產(chǎn)環(huán)境的隔離級(jí)別對(duì)樂(lè)觀鎖的影響,通過(guò)簡(jiǎn)單驗(yàn)證,展示了在可重復(fù)讀和讀已提交隔離級(jí)別下的不同行為,感興趣的朋友一起看看吧2025-03-03
MyEclipse如何將項(xiàng)目的開(kāi)發(fā)環(huán)境與服務(wù)器的JDK 版本保持一致
我們使用MyEclipse開(kāi)發(fā)Java項(xiàng)目開(kāi)發(fā)中,偶爾會(huì)遇到因項(xiàng)目開(kāi)發(fā)環(huán)境不協(xié)調(diào),導(dǎo)致這樣那樣的問(wèn)題,在這里以把所有環(huán)境調(diào)整為JDK1.6 為例,給大家詳細(xì)介紹MyEclipse如何將項(xiàng)目的開(kāi)發(fā)環(huán)境與服務(wù)器的JDK 版本保持一致,需要的朋友參考下吧2024-04-04
基于Java實(shí)現(xiàn)簡(jiǎn)單的郵件群發(fā)功能
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言編寫(xiě)一個(gè)簡(jiǎn)單的工具類(lèi),可以實(shí)現(xiàn)郵件群發(fā)功能。文中的示例代碼講解詳細(xì),需要的可以參考一下2022-05-05
java input 調(diào)用手機(jī)相機(jī)和本地照片上傳圖片到服務(wù)器然后壓縮的方法
今天小編就為大家分享一篇java input 實(shí)現(xiàn)調(diào)用手機(jī)相機(jī)和本地照片上傳圖片到服務(wù)器然后壓縮的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08

