import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.OceanTheme;
public class Dinner extends JFrame {
private final int personCount = 10; //哲学家数量
private Room room = new Room(2);//房间锁变量,用于控制同时就餐的人数dd
private JButton startBtn = new JButton("开始");
private JButton stopBtn = new JButton("暂停");
private JButton continueBtn = new JButton("继续");
private JButton endBtn = new JButton("结束");
private volatile boolean started = false;
private volatile boolean stopped = false;
final Chopstick[] chopstick = new Chopstick[personCount];
final Philosopher[] philos = new Philosopher[personCount];
private ImageIcon normalFace, eatFace, thinkFace, hungryFace; //表情图片
/**
* 因Table(餐桌)类与Dinner类联系较为紧密,故将其作为内部类,方便消息的传递
*/
class DinnerTable extends JPanel {
private int counts;
private int r1 = 20;
private int CHOPS_LENGTH = 35; //筷子的长度
private int DISTANCE = 100; //筷子与人的距离
private int VERTICAL_DIS = -20; //表情与名字的距离
private int r2 = r1 + CHOPS_LENGTH;
private int r3 = r2 + DISTANCE;
private int delta;
private int delta0 = -18;
public DinnerTable(int counts) {
setOpaque(false);
this.setPreferredSize(new Dimension(550, 400));
this.counts = counts;
this.delta = 360 / counts;
}
@Override
public void paintComponent(Graphics page) {
super.paintComponent(page);
int x1, y1, x2, y2, x3, y3;
page.fillOval(200, 150, 150, 150);
//画餐桌上的筷子
for (int i = 0; i < counts; i++) {
page.setColor(Color.YELLOW);
//根据坐标系 x = r*cos(delta) , y = r*sin(delta) 计算点
x1 = 275 + (int) (r1 * Math.cos(((delta * i) + delta0 * (-5)) * Math.PI / 180));
y1 = 225 + (int) (r1 * Math.sin(((delta * i) + delta0 * (-5)) * Math.PI / 180));
x2 = 275 + (int) (r2 * Math.cos(((delta * i) + delta0 * (-5)) * Math.PI / 180));
y2 = 225 + (int) (r2 * Math.sin(((delta * i) + delta0 * (-5)) * Math.PI / 180));
x3 = 275 + (int) (r3 * Math.cos(((delta * i) + delta0) * Math.PI / 180));
y3 = 225 + (int) (r3 * Math.sin(((delta * i) + delta0) * Math.PI / 180));
if (chopstick[i].getOwner() != null && philos[i].getPersonId() == chopstick[i].getOwnerId()) {
//检查哲学家是否拿到左边筷子
page.drawLine(x3 - 20, y3, x3 - 20, y3 + CHOPS_LENGTH);
}
if (chopstick[(i + 1) % personCount].getOwner() != null && philos[i].getPersonId() == chopstick[(i + 1) % personCount].getOwnerId()) {
//检查哲学家是否拿到右边筷子
page.drawLine(x3 + 45, y3, x3 + 45, y3 + CHOPS_LENGTH);
}
if (chopstick[i].getOwner() == null) {
//筷子在餐桌上
page.drawLine(x1, y1, x2, y2);
}
philos[i].getFace().paintIcon(this, page, x3, y3); //画表情
page.setColor(Color.BLUE);
page.drawString("哲学家" + (i + 1), x3 - 5, y3 + VERTICAL_DIS);//画名字
}
}
}
/**
* 设置窗口居中
*/
private void putUIInCenter() {
int windowWidth = this.getWidth(); //获得窗口宽
int windowHeight = this.getHeight(); //获得窗口高
Toolkit kit = Toolkit.getDefaultToolkit(); //定义工具包
Dimension screenSize = kit.getScreenSize(); //获取屏幕的尺寸
int screenWidth = screenSize.width; //获取屏幕的宽
int screenHeight = screenSize.height; //获取屏幕的高
this.setLocation(screenWidth / 2 - windowWidth / 2, screenHeight / 2 - windowHeight / 2);
}
public Dinner() {
setTitle("哲学家就餐");
setPreferredSize(new Dimension(600, 650));
this.pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
putUIInCenter();
normalFace = new ImageIcon("init.png");
eatFace = new ImageIcon("eat.png");
thinkFace = new ImageIcon("think.png");
hungryFace = new ImageIcon("hungry.png");
JPanel btnPanel = new JPanel();
btnPanel.setBounds(160, 20, 300, 200);
btnPanel.setOpaque(false);
btnPanel.setLayout(new FlowLayout());
btnPanel.add(startBtn);
btnPanel.add(stopBtn);
btnPanel.add(continueBtn);
btnPanel.add(endBtn);
//各种按钮增加点击事件
startBtn.addActionListener((e) -> {
if (!started) {
started = true;
for (int i = 0; i < personCount; i++) {
philos[i].start();
}
}
});
continueBtn.addActionListener((e) -> {
if (stopped) {
for (int i = 0; i < personCount; i++) {
philos[i].resume();
}
stopped = false;
}
});
stopBtn.addActionListener((e) -> {
for (int i = 0; i < personCount; i++) {
philos[i].suspend();
}
stopped = true;
});
endBtn.addActionListener((e) -> {
System.exit(1);
});
JPanel mainPanel = new JPanel();
mainPanel.setLayout(null);
mainPanel.setBackground(Color.black);
mainPanel.add(btnPanel);
DinnerTable table = new DinnerTable(personCount);
table.setBounds(20, 50, 500, 420);
for (int i = 0; i < chopstick.length; i++) {
chopstick[i] = new Chopstick(i, table);
}
for (int i = 0; i < philos.length; i++) {
philos[i] = new Philosopher(room, i,
chopstick[i], chopstick[(i + 1) % personCount]);
}
mainPanel.add(table);
JPanel descripPanel = new JPanel();
descripPanel.setBounds(20, 480, 200, 200);
descripPanel.setOpaque(false);
descripPanel.setForeground(Color.red);
descripPanel.setLayout(new BoxLayout(descripPanel, BoxLayout.Y_AXIS));
JLabel label0 = new JLabel("哲学家就餐问题(信号量解决)");
label0.setForeground(Color.red);
JLabel label1 = new JLabel("初始状态的哲学家", normalFace, JLabel.RIGHT);
label1.setForeground(Color.red);
JLabel label2 = new JLabel("思考状态的哲学家", thinkFace, JLabel.RIGHT);
label2.setForeground(Color.red);
JLabel label3 = new JLabel("饥饿状态的哲学家", hungryFace, JLabel.RIGHT);
label3.setForeground(Color.red);
JLabel label4 = new JLabel("正在吃饭的哲学家", eatFace, JLabel.RIGHT);
label4.setForeground(Color.red);
descripPanel.add(label0);
descripPanel.add(label1);
descripPanel.add(label2);
descripPanel.add(label3);
descripPanel.add(label4);
mainPanel.add(descripPanel);
getContentPane().add(mainPanel);
setVisible(true);
}
publ