Java 实现生产者消费者问题:线程同步与互斥、图形化界面
本文将介绍如何在 Windows 操作系统下,使用 Java 语言,采用进程(线程)同步和互斥的技术编写程序实现生产者-消费者问题,并书写界面图形化的代码。由于题目中没有明确要求使用哪种图形化界面编程工具,因此本篇答案将使用 Java Swing 编写图形化界面的代码。
首先,我们需要定义一个共享缓冲区,用于生产者和消费者之间的数据交换。假设缓冲区的大小为 10,定义如下:
public class Buffer {
private int[] buffer;
private int size;
private int in; // 生产者写入位置
private int out; // 消费者读取位置
private int count; // 缓冲区中的数据数量
public Buffer(int size) {
this.buffer = new int[size];
this.size = size;
this.in = 0;
this.out = 0;
this.count = 0;
}
public synchronized void put(int data) throws InterruptedException {
while (count == size) { // 缓冲区已满,等待消费者读取
wait();
}
buffer[in] = data;
in = (in + 1) % size;
count++;
notifyAll(); // 通知消费者可以读取数据了
}
public synchronized int get() throws InterruptedException {
while (count == 0) { // 缓冲区为空,等待生产者写入
wait();
}
int data = buffer[out];
out = (out + 1) % size;
count--;
notifyAll(); // 通知生产者可以写入数据了
return data;
}
}
其中,put 方法表示生产者往缓冲区中写入数据,get 方法表示消费者从缓冲区中读取数据。这两个方法都使用了 synchronized 关键字,实现了进程(线程)同步和互斥。
接下来,我们需要编写生产者和消费者的代码。这里我们定义一个 Producer 类和一个 Consumer 类,它们都需要访问缓冲区。代码如下:
public class Producer implements Runnable {
private Buffer buffer;
public Producer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
try {
for (int i = 0; i < 100; i++) {
buffer.put(i);
Thread.sleep((int) (Math.random() * 100));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Consumer implements Runnable {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
try {
while (true) {
int data = buffer.get();
System.out.println(data);
Thread.sleep((int) (Math.random() * 100));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
最后,我们需要编写图形化界面的代码。这里我们使用 Java Swing 库,创建一个窗口,包含一个文本框和一个按钮。点击按钮后,启动一个新的线程作为生产者,同时在文本框中显示生产者的状态。点击另一个按钮后,启动一个新的线程作为消费者,同时在文本框中显示消费者的状态。代码如下:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MainFrame extends JFrame {
private JTextArea textArea;
private JButton producerButton;
private JButton consumerButton;
private Buffer buffer;
public MainFrame() {
super('生产者消费者问题');
buffer = new Buffer(10);
textArea = new JTextArea(10, 30);
textArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(textArea);
producerButton = new JButton('启动生产者');
producerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Producer producer = new Producer(buffer);
Thread thread = new Thread(producer);
thread.start();
textArea.append('启动生产者线程\n');
}
});
consumerButton = new JButton('启动消费者');
consumerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Consumer consumer = new Consumer(buffer);
Thread thread = new Thread(consumer);
thread.start();
textArea.append('启动消费者线程\n');
}
});
JPanel panel = new JPanel();
panel.add(producerButton);
panel.add(consumerButton);
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(scrollPane, BorderLayout.CENTER);
contentPane.add(panel, BorderLayout.SOUTH);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
new MainFrame();
}
}
运行程序后,可以点击“启动生产者”和“启动消费者”按钮,观察生产者和消费者的状态,验证生产者消费者问题的解决方案。
原文地址: https://www.cveoy.top/t/topic/nG3h 著作权归作者所有。请勿转载和采集!