桌子上有一只盘子,最多可容纳两个水果,每次只能放入或取出一个水果。爸爸专向盘子放苹果 (apple),妈妈专向盘子中放桔子 (orange):两个儿子专等吃盘子中的桔子,两个女儿专等吃盘子中的苹果。请使用程序模拟实现爸爸、妈妈、儿子、女儿之间的同步与互斥关系。 [设计要求] 1.设计一程序,创建6个线程,分别模拟表示爸爸、妈妈、两个儿子和两个女儿操作过程。 2.所有的6个线程须互斥对盘子进行操作。 3.采用可视化界面,可在运行过程中随时暂停,查看当前6个线程的状态、盘子的使用情况。
时间: 2024-02-18 11:01:54 浏览: 167
实现这个问题可以使用Java中的多线程和GUI技术来完成。下面是一个简单的实现方式:
```
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.Semaphore;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class FruitPlate extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private JLabel labelApple; // 苹果数量标签
private JLabel labelOrange; // 桔子数量标签
private JButton buttonFather; // 爸爸按钮
private JButton buttonMother; // 妈妈按钮
private JButton buttonSon; // 儿子按钮
private JButton buttonDaughter; // 女儿按钮
private JPanel panelPlate; // 盘子面板
private Semaphore semaphore; // 信号量
private int appleCount = 0; // 苹果数量
private int orangeCount = 0; // 桔子数量
public FruitPlate() {
super("水果盘子");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// 盘子面板
panelPlate = new JPanel(new GridLayout(1, 2));
panelPlate.setBackground(Color.WHITE);
JLabel labelAppleTitle = new JLabel("苹果");
labelAppleTitle.setFont(new Font("宋体", Font.BOLD, 20));
labelAppleTitle.setHorizontalAlignment(JLabel.CENTER);
panelPlate.add(labelAppleTitle);
JLabel labelOrangeTitle = new JLabel("桔子");
labelOrangeTitle.setFont(new Font("宋体", Font.BOLD, 20));
labelOrangeTitle.setHorizontalAlignment(JLabel.CENTER);
panelPlate.add(labelOrangeTitle);
labelApple = new JLabel("0");
labelApple.setFont(new Font("宋体", Font.BOLD, 20));
labelApple.setHorizontalAlignment(JLabel.CENTER);
panelPlate.add(labelApple);
labelOrange = new JLabel("0");
labelOrange.setFont(new Font("宋体", Font.BOLD, 20));
labelOrange.setHorizontalAlignment(JLabel.CENTER);
panelPlate.add(labelOrange);
add(panelPlate, BorderLayout.NORTH);
// 操作按钮面板
JPanel panelButtons = new JPanel(new FlowLayout());
buttonFather = new JButton("爸爸放苹果");
buttonFather.addActionListener(this);
panelButtons.add(buttonFather);
buttonMother = new JButton("妈妈放桔子");
buttonMother.addActionListener(this);
panelButtons.add(buttonMother);
buttonSon = new JButton("儿子取桔子");
buttonSon.addActionListener(this);
panelButtons.add(buttonSon);
buttonDaughter = new JButton("女儿取苹果");
buttonDaughter.addActionListener(this);
panelButtons.add(buttonDaughter);
add(panelButtons, BorderLayout.CENTER);
// 信号量
semaphore = new Semaphore(1);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if ("爸爸放苹果".equals(command)) {
new Thread(new FatherThread()).start();
} else if ("妈妈放桔子".equals(command)) {
new Thread(new MotherThread()).start();
} else if ("儿子取桔子".equals(command)) {
new Thread(new SonThread()).start();
} else if ("女儿取苹果".equals(command)) {
new Thread(new DaughterThread()).start();
}
}
// 爸爸线程
private class FatherThread implements Runnable {
@Override
public void run() {
try {
semaphore.acquire(); // 获取信号量
if (appleCount + orangeCount < 2) {
appleCount++;
labelApple.setText(String.valueOf(appleCount));
System.out.println("爸爸放了一个苹果,盘子中有" + appleCount + "个苹果和" + orangeCount + "个桔子");
} else {
System.out.println("盘子已满,爸爸不放了");
}
semaphore.release(); // 释放信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 妈妈线程
private class MotherThread implements Runnable {
@Override
public void run() {
try {
semaphore.acquire(); // 获取信号量
if (appleCount + orangeCount < 2) {
orangeCount++;
labelOrange.setText(String.valueOf(orangeCount));
System.out.println("妈妈放了一个桔子,盘子中有" + appleCount + "个苹果和" + orangeCount + "个桔子");
} else {
System.out.println("盘子已满,妈妈不放了");
}
semaphore.release(); // 释放信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 儿子线程
private class SonThread implements Runnable {
@Override
public void run() {
try {
semaphore.acquire(); // 获取信号量
if (orangeCount > 0) {
orangeCount--;
labelOrange.setText(String.valueOf(orangeCount));
System.out.println("儿子取了一个桔子,盘子中有" + appleCount + "个苹果和" + orangeCount + "个桔子");
} else {
System.out.println("盘子中没有桔子了,儿子不能取");
}
semaphore.release(); // 释放信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 女儿线程
private class DaughterThread implements Runnable {
@Override
public void run() {
try {
semaphore.acquire(); // 获取信号量
if (appleCount > 0) {
appleCount--;
labelApple.setText(String.valueOf(appleCount));
System.out.println("女儿取了一个苹果,盘子中有" + appleCount + "个苹果和" + orangeCount + "个桔子");
} else {
System.out.println("盘子中没有苹果了,女儿不能取");
}
semaphore.release(); // 释放信号量
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new FruitPlate();
}
}
```
在上面的代码中,使用了一个信号量来实现线程的同步和互斥,盘子的容量为2,当盘子中已经有2个水果时,爸爸和妈妈不能再放入水果,儿子和女儿不能再取出水果。当某个线程获取到信号量时,它可以执行操作,操作完成后释放信号量。通过这种方式,可以保证线程的安全性。
界面中的四个按钮分别对应爸爸、妈妈、儿子和女儿,点击按钮后会启动对应的线程执行操作,同时也可以看到盘子中水果数量的变化。在程序运行过程中,可以通过暂停按钮来查看当前线程和盘子的状态。
阅读全文