1.标红的地方为算法的主要思想所在,理解了便十分简单了,不理解可以根据注释。
在这个算法中有个很巧妙的地方,便是用一个数组来表示哲学家是否在就餐。
package test3;
import java.util.concurrent.Semaphore;
class Philosopher extends Thread {
int id;
private Chopsticsks chopsticsks;
public Philosopher(int num,Chopsticsks chopsticsks) {
super();
id=num;
this.chopsticsks = chopsticsks;
}
public void run() {
while (true) {
thinking();
chopsticsks.take(id);
System.out.println("哲学家"+id+"拿起左边筷子"+id);
chopsticsks.take((id+1)%5);
System.out.println("哲学家"+id+"拿起右边筷子"+(id+1)%5);
eating();
chopsticsks.put();
}
}
private void thinking() {
System.out.println("哲学家 " + id + ": 开始思考!");
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void eating() {
System.out.println("哲学家" + id+ " : 开始食用!");
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Chopsticsks {
private boolean[] used = { false, false, false, false, false }; //初始化筷子为未使用
private int[] num= {0,0,0,0,0}; //记录进餐的哲学家人数
//统计除自己以外进餐的人数
public synchronized int getNum(int id) {
int n=0;
for(int i=0;i<5;++i) {
if(num[i]==1 && i!=id) {
++n;
}
}
return n;
}
public synchronized void take(int chop) {
Philosopher p = (Philosopher) Thread.currentThread();
int id = p.id;
while(getNum(id)>=4 || used[chop])
{
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
used[chop]=true;
num[id]=1; //根据Id来赋值,避免了重复算拿两只筷子。
}
@SuppressWarnings("deprecation")
public synchronized void put() {
Philosopher p = (Philosopher) Thread.currentThread();
int id = p.id;
System.out.println("哲学家" + id + "放下手中的筷子:"+id+"、" +(id + 1) % 5);
used[id] = false; //将筷子设为为使用
used[(id + 1) % 5] = false;
num[id]=0;
notifyAll(); //唤醒所有等待队列中的进程
}
}
public class Test {
public static void main(String[] args) {
Chopsticsks chopsticsks = new Chopsticsks();
new Philosopher(0,chopsticsks).start();
new Philosopher(1,chopsticsks).start();
new Philosopher(2,chopsticsks).start();
new Philosopher(3,chopsticsks).start();
new Philosopher(4,chopsticsks).start();
}
}
2.结果截图