import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.ImageIcon;
//叉子类
class Forks {
boolean fState; //互斥信号量
JLabel fLabel; //显示叉子的JLabel
ImageIcon emptyImage,forkImage; //被用时为empty图片,否则为叉子图片
public Forks(JLabel bLabel, ImageIcon image) {
emptyImage=new ImageIcon("空的.jpg");
this.fLabel=bLabel;
this.forkImage=image;
fState=true; //一开始都设叉子为可用状态
}
public synchronized void gainFork() {
while(!fState) { //如果此叉子已被用,则等待
try {
wait();
}catch(Exception e) {
e.printStackTrace();
}
}
fLabel.setIcon(emptyImage); //获得叉子,并把叉子所代表 的图片设为空
fState=false; //把此叉子的状态设为已被用了
}
public synchronized void laydownFork() { //放下叉子,把叉子状态设为可用
fState=true;
fLabel.setIcon(forkImage);
notify(); //唤醒其他在等待的线程,如果有等待此叉子的线程,则可以继续判断
}
}
//哲学家类,
class Philosophy extends Thread {
int thinkTime, eatTime; // 思考,吃饭的时间
Forks left, right; // 哲学家的左右叉子
int num; // 第几号哲学家
JLabel zxjLable, leftLable, rightLable, zxjLeftLabel, zxjRightLabel; // zxjLable为哲学家设置状态的,
// leftLable,rightLable,为哲学家设置左右两根叉子的,
// zxjLeftLabel,zxjRightLabel为哲学家设置拿起两叉子的
ImageIcon leftImage, rightImage; //左右两个筷子的图片
Philosophy(int num, JLabel zLabel, Forks left, JLabel lLabel,
Forks right, // 哲学家构造函数
JLabel rLabel, ImageIcon lImage, ImageIcon rImage, JLabel zLLabel,
JLabel zRLabel) {
this.num = num;
this.zxjLable = zLabel;
this.left = left;
this.leftLable = lLabel;
this.right = right;
this.rightLable = rLabel;
this.leftImage = lImage;
this.rightImage = rImage;
this.zxjRightLabel = zRLabel;
this.zxjLeftLabel = zLLabel;
}
public void run() {
ImageIcon thinkImage = new ImageIcon("thinking.gif");
ImageIcon huangryImage = new ImageIcon("huangry.gif");
ImageIcon eatImage = new ImageIcon("eating.gif");
ImageIcon empty = new ImageIcon("empty.jpg");
while (true) {
zxjLable.setIcon(thinkImage);
do {
thinkTime = (int) (Math.random() * 10000); // 获得随机的思考时间
} while (thinkTime < 1500);
try {
sleep(thinkTime); // 以线程睡眠的方式让哲学家思考一些时间
} catch (Exception e) {
}
zxjLable.setIcon(huangryImage);
left.gainFork(); // 获得左边的叉子
zxjLeftLabel.setIcon(leftImage);
right.gainFork(); // 获得右边的叉子
zxjRightLabel.setIcon(rightImage);
zxjLable.setIcon(eatImage);
do {
eatTime = (int) (Math.random() * 10000); // 获得随机的吃饭时间
} while (eatTime < 1500);
try {
sleep(eatTime); // 以线程睡眠的方式让哲学家吃饭一些时间
} catch (Exception e) {
}
synchronized (left) {
left.laydownFork(); // 放下左边的叉子
zxjLeftLabel.setIcon(empty);
}
synchronized (right) {
right.laydownFork(); // 放下右边的叉子
zxjRightLabel.setIcon(empty);
}
}
}
}
//主类
public class philosopher extends JFrame implements ActionListener {
JButton start_Button,Exit_Button;
JLabel forkLabel[];
JLabel Gbc[];
JLabel phiLable[];
Forks Fork[]; // 叉子对象数组
Philosophy zxj[]; // 哲学家对象数组
ImageIcon forkImage[],empty,thinkImage,huangryImage,eatImage;
philosopher()
{ // 构造函数
super(" 不死锁哲学家就餐问题模拟 ");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container C=this.getContentPane();
C.setBackground(java.awt.Color.WHITE);
thinkImage=new ImageIcon("thinking.gif");
huangryImage=new ImageIcon("huangry.gif");
eatImage=new ImageIcon("eating.gif");
empty=new ImageIcon("空的.gif");
JPanel panel=new JPanel();
panel.setLayout(new FlowLayout());
phiLable=new JLabel[6];
for(int i=1;i<=5;i++) {
phiLable[i]=new JLabel();
phiLable[i].setIcon(thinkImage); //一开始设为思考
}
forkImage=new ImageIcon[6];
forkImage[1]=new ImageIcon("fork.jpg");
forkImage[2]=new ImageIcon("fork.jpg");
forkImage[3]=new ImageIcon("fork.jpg");
forkImage[4]=new ImageIcon("fork.jpg");
forkImage[5]=new ImageIcon("fork.jpg");
forkLabel=new JLabel[6];
forkLabel[1]=new JLabel(); forkLabel[1].setIcon(forkImage[1]);
forkLabel[2]=new JLabel(); forkLabel[2].setIcon(forkImage[2]);
forkLabel[3]=new JLabel(); forkLabel[3].setIcon(forkImage[3]);
forkLabel[4]=new JLabel(); forkLabel[4].setIcon(forkImage[4]);
forkLabel[5]=new JLabel(); forkLabel[5].setIcon(forkImage[5]);
Fork=new Forks[6];
for(int i=1;i<=5;i++) Fork[i]=new Forks(forkLabel[i],forkImage[i]); //叉子对象的初始化
Gbc=new JLabel[13];
for(int i=1;i<=12;i++) {
Gbc[i]=new JLabel();
Gbc[i].setIcon(empty);
}
zxj=new Philosophy[6];
panel=new JPanel();
panel.setLayout(new GridBagLayout());
//GridBagLayout 类是一个灵活的布局管理器,
//它不要求组件的大小相同即可将组件垂直和水平对齐。
//每个 GridBagLayout 对象维持一个动态的矩形单元网格,
//每个组件占用一个或多个这样的单元,称为显示区域。
GridBagConstraints gbc=new GridBagConstraints();
//GridBagConstraints 类指定使用 GridBagLayout 类布置的组件的约束。
//详细见E盘api
//
gbc.weightx=1; gbc.weighty=1;
gbc.gridwidth=1; gbc.gridheight=1;
gbc.gridy=0;
gbc.gridx=4; panel.add(Gbc[2],gbc);
gbc.gridx=6; panel.add(Gbc[1],gbc);
gbc.gridy=1;
gbc.gridx=5; panel.add(phiLable[1],gbc);
gbc.gridy=2;
gbc.gridx=0; panel.add(Gbc[3],gbc);
gbc.gridx=3; panel.add(forkLabel[1],gbc);
gbc.gridx=7; panel.add(forkLabel[5],gbc);
gbc.gridx=10; panel.add(Gbc[10],gbc);
gbc.gridy=3;
gbc.gridx=1; panel.add(phiLable[2],gbc);
gbc.gridx=9; panel.add(phiLable[5],gbc);
gbc.gridy=4;
gbc.gridx=0; panel.add(Gbc[4],gbc);
gbc.gridx=10; panel.add(Gbc[9],gbc);
gbc.gridy=5;
gbc.gridx=2; panel.add(forkLabel[2],gbc);
gbc.gridx=8; panel.add(forkLabel[4],gbc);
gbc.gridy=7;
gbc.gridx=2; panel.add(Gbc[5],gbc);
gbc.gridx=3; panel.add(phiLable[3],gbc);
gbc.gridx=7; panel.add(phiLable[4],gbc);
gbc.gridx=8; panel.add(Gbc[8],gbc);
gbc.gridy=8;
gbc.gridx=3; panel.add(Gbc[6],gbc);
gbc.gridx=5; panel.add(forkLabel[3],gbc);
gbc.gridx=7; panel.add(Gbc[7],gbc);
C.add(panel,BorderLayout.CENTER);
zxj[1]=new Philosophy(1, phiLable[1], Fork[5], forkLabel[5],
Fork[1], forkLabel[1], forkImage[5], forkImage[1], Gbc[1], Gbc[2]);
zxj[2]=new Philosophy(2, phiLable[2],Fork[2], forkLabel[2],
Fork[1], forkLabel[1], forkImage[2], forkImage[1], Gbc[4], Gbc[3]);
zxj[3]=new Philosophy(3, phiLable[3], Fork[2], forkLabel[2],
Fork[3]