使用 Java Swing 实现生产者-消费者问题:多线程同步与互斥

本文将使用 Java Swing 库,通过多线程同步和互斥技术,编写生产者-消费者问题示例程序,并提供图形化界面展示生产和消费过程。

代码示例

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ProducerConsumer extends JFrame implements ActionListener {
    private final Object lock = new Object();
    private JLabel label;
    private JButton startButton, stopButton;
    private JTextArea producerTextArea, consumerTextArea;
    private Thread producerThread, consumerThread;
    private boolean running = false;
    private int buffer = 0;

    public ProducerConsumer() {
        setTitle('Producer-Consumer Problem');
        setSize(400, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel1 = new JPanel();
        panel1.setLayout(new FlowLayout());
        label = new JLabel('Buffer: ' + buffer);
        panel1.add(label);

        JPanel panel2 = new JPanel();
        panel2.setLayout(new GridLayout(1, 2));
        producerTextArea = new JTextArea(10, 20);
        producerTextArea.setEditable(false);
        JScrollPane producerScrollPane = new JScrollPane(producerTextArea);
        panel2.add(producerScrollPane);
        consumerTextArea = new JTextArea(10, 20);
        consumerTextArea.setEditable(false);
        JScrollPane consumerScrollPane = new JScrollPane(consumerTextArea);
        panel2.add(consumerScrollPane);

        JPanel panel3 = new JPanel();
        panel3.setLayout(new FlowLayout());
        startButton = new JButton('Start');
        startButton.addActionListener(this);
        panel3.add(startButton);
        stopButton = new JButton('Stop');
        stopButton.addActionListener(this);
        stopButton.setEnabled(false);
        panel3.add(stopButton);

        Container contentPane = getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(panel1, BorderLayout.NORTH);
        contentPane.add(panel2, BorderLayout.CENTER);
        contentPane.add(panel3, BorderLayout.SOUTH);
    }

    public static void main(String[] args) {
        ProducerConsumer frame = new ProducerConsumer();
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == startButton) {
            running = true;
            startButton.setEnabled(false);
            stopButton.setEnabled(true);
            producerThread = new Thread(new ProducerRunnable());
            consumerThread = new Thread(new ConsumerRunnable());
            producerThread.start();
            consumerThread.start();
        } else if (e.getSource() == stopButton) {
            running = false;
            startButton.setEnabled(true);
            stopButton.setEnabled(false);
            producerThread.interrupt();
            consumerThread.interrupt();
        }
    }

    private class ProducerRunnable implements Runnable {
        public void run() {
            while (running) {
                synchronized (lock) {
                    while (buffer >= 10) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            return;
                        }
                    }
                    buffer++;
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            label.setText('Buffer: ' + buffer);
                            producerTextArea.append('Produced 1 item\n');
                        }
                    });
                    lock.notifyAll();
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    return;
                }
            }
        }
    }

    private class ConsumerRunnable implements Runnable {
        public void run() {
            while (running) {
                synchronized (lock) {
                    while (buffer <= 0) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            return;
                        }
                    }
                    buffer--;
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            label.setText('Buffer: ' + buffer);
                            consumerTextArea.append('Consumed 1 item\n');
                        }
                    });
                    lock.notifyAll();
                }
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    return;
                }
            }
        }
    }
}

代码说明

  1. GUI 界面: 使用 Java Swing 库创建图形界面,包含显示缓冲区状态的标签、展示生产者和消费者操作日志的文本区域,以及控制程序运行的“Start”和“Stop”按钮。
  2. 生产者和消费者线程: 分别创建 ProducerRunnableConsumerRunnable 类,实现生产者和消费者的线程逻辑。
  3. 同步与互斥: 使用 synchronized 关键字和 lock 对象保证对共享变量 buffer 的访问是同步的。生产者和消费者线程使用 wait()notifyAll() 方法进行协调。
  4. 界面更新: 使用 SwingUtilities.invokeLater() 方法将界面更新操作放在事件调度线程中,确保界面操作在安全线程中执行。
  5. 延迟模拟: 使用 Thread.sleep() 方法模拟生产和消费过程中的延迟。
  6. 按钮事件处理: 使用 actionPerformed() 方法处理“Start”和“Stop”按钮的单击事件,控制线程的启动和停止。

运行结果

运行程序后,会显示一个包含标签、文本区域和按钮的窗口。单击“Start”按钮开始模拟生产者-消费者问题,界面将实时显示缓冲区状态和生产/消费日志。单击“Stop”按钮停止模拟。

总结

本文通过一个简单的示例程序,展示了如何使用 Java Swing 库和多线程技术实现生产者-消费者问题,并提供图形化界面进行展示。希望本文能帮助读者了解多线程同步和互斥的概念,以及如何在实际应用中使用它们解决并发访问问题。

注意: 本文仅提供一个简单的示例程序,实际应用中可能需要更复杂的逻辑和功能。请根据实际需求进行调整和扩展。

Java Swing 实现生产者-消费者问题:多线程同步与互斥

原文地址: https://www.cveoy.top/t/topic/nG3V 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录