Java仿真案例

wen java案例 1

本文目录导读:

Java仿真案例

  1. 银行排队系统仿真
  2. 仿真案例说明

我为您提供一个完整的Java多线程仿真案例——银行排队系统仿真,包含详细代码和设计说明。

银行排队系统仿真

系统设计

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
/**
 * 银行排队系统仿真
 * 模拟银行柜台服务、客户到达、排队等待等场景
 */
public class BankSimulation {
    // 仿真参数
    private static final int NUM_COUNTERS = 5;          // 柜台数量
    private static final int SIMULATION_MINUTES = 30;   // 仿真时长(分钟)
    private static final int MAX_ARRIVE_INTERVAL = 3000; // 最大到达间隔(毫秒)
    private static final int MIN_ARRIVE_INTERVAL = 500;  // 最小到达间隔(毫秒)
    private static final int MAX_SERVICE_TIME = 5000;    // 最大服务时间(毫秒)
    private static final int MIN_SERVICE_TIME = 1000;    // 最小服务时间(毫秒)
    // 统计数据
    private static AtomicInteger totalCustomers = new AtomicInteger(0);
    private static AtomicInteger servedCustomers = new AtomicInteger(0);
    private static AtomicLong totalWaitingTime = new AtomicLong(0);
    private static AtomicInteger maxQueueLength = new AtomicInteger(0);
    // 共享队列
    private static BlockingQueue<Customer> customerQueue = new LinkedBlockingQueue<>();
    public static void main(String[] args) {
        System.out.println("===== 银行排队系统仿真开始 =====");
        System.out.println("仿真时长:" + SIMULATION_MINUTES + "分钟");
        System.out.println("柜台数量:" + NUM_COUNTERS);
        System.out.println("================================\n");
        // 启动仿真
        long startTime = System.currentTimeMillis();
        long endTime = startTime + SIMULATION_MINUTES * 60 * 1000;
        // 创建并启动柜台服务线程
        List<Thread> counterThreads = new ArrayList<>();
        for (int i = 0; i < NUM_COUNTERS; i++) {
            Counter counter = new Counter("柜台-" + (i + 1));
            Thread thread = new Thread(counter);
            thread.setName("Counter-" + (i + 1));
            thread.start();
            counterThreads.add(thread);
        }
        // 创建客户到达生成器
        CustomerGenerator generator = new CustomerGenerator(endTime);
        Thread generatorThread = new Thread(generator, "CustomerGenerator");
        generatorThread.start();
        // 监控线程
        Thread monitorThread = new Thread(new Monitor(endTime), "Monitor");
        monitorThread.setDaemon(true);
        monitorThread.start();
        // 等待仿真结束
        try {
            generatorThread.join();
            // 等待队列处理完剩余客户
            Thread.sleep(5000);
            // 停止柜台线程
            Counter.shutdown();
            for (Thread t : counterThreads) {
                t.join(2000);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        // 输出统计结果
        printStatistics(startTime);
        System.out.println("\n===== 仿真结束 =====");
    }
    /**
     * 客户类
     */
    static class Customer {
        private final int id;
        private final long arrivalTime;
        private final long serviceTime;
        public Customer(int id, long arrivalTime, long serviceTime) {
            this.id = id;
            this.arrivalTime = arrivalTime;
            this.serviceTime = serviceTime;
        }
        public int getId() { return id; }
        public long getArrivalTime() { return arrivalTime; }
        public long getServiceTime() { return serviceTime; }
    }
    /**
     * 客户到达生成器
     */
    static class CustomerGenerator implements Runnable {
        private final long endTime;
        private final Random random = new Random();
        public CustomerGenerator(long endTime) {
            this.endTime = endTime;
        }
        @Override
        public void run() {
            int customerId = 0;
            while (System.currentTimeMillis() < endTime) {
                // 随机生成到达间隔
                int interval = MIN_ARRIVE_INTERVAL + 
                    random.nextInt(MAX_ARRIVE_INTERVAL - MIN_ARRIVE_INTERVAL + 1);
                try {
                    Thread.sleep(interval);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return;
                }
                // 创建新客户并加入队列
                Customer customer = new Customer(
                    ++customerId,
                    System.currentTimeMillis(),
                    MIN_SERVICE_TIME + 
                    random.nextInt(MAX_SERVICE_TIME - MIN_SERVICE_TIME + 1)
                );
                customerQueue.offer(customer);
                totalCustomers.incrementAndGet();
                // 更新最大队列长度
                int currentQueueLength = customerQueue.size();
                maxQueueLength.set(Math.max(maxQueueLength.get(), currentQueueLength));
                System.out.printf("%s: 客户#%d到达 | 队列长度: %d%n",
                    getCurrentTime(), customerId, currentQueueLength);
            }
            System.out.println("客户到达生成器停止工作");
        }
    }
    /**
     * 柜台服务线程
     */
    static class Counter implements Runnable {
        private static final AtomicBoolean shutdownFlag = new AtomicBoolean(false);
        private final String counterName;
        public Counter(String counterName) {
            this.counterName = counterName;
        }
        public static void shutdown() {
            shutdownFlag.set(true);
        }
        @Override
        public void run() {
            System.out.println(counterName + " 开始服务");
            while (!shutdownFlag.get() || !customerQueue.isEmpty()) {
                try {
                    // 尝试获取客户,等待最多500毫秒
                    Customer customer = customerQueue.poll(500, TimeUnit.MILLISECONDS);
                    if (customer != null) {
                        // 计算等待时间
                        long waitingTime = System.currentTimeMillis() - customer.getArrivalTime();
                        totalWaitingTime.addAndGet(waitingTime);
                        servedCustomers.incrementAndGet();
                        System.out.printf("%s: %s开始服务客户#%d | 等待时间: %.2f秒%n",
                            getCurrentTime(), counterName, customer.getId(), waitingTime / 1000.0);
                        // 模拟服务时间
                        Thread.sleep(customer.getServiceTime());
                        System.out.printf("%s: %s完成服务客户#%d | 服务时间: %.2f秒%n",
                            getCurrentTime(), counterName, customer.getId(), 
                            customer.getServiceTime() / 1000.0);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            System.out.println(counterName + " 停止服务");
        }
    }
    /**
     * 监控线程 - 定期输出系统状态
     */
    static class Monitor implements Runnable {
        private final long endTime;
        public Monitor(long endTime) {
            this.endTime = endTime;
        }
        @Override
        public void run() {
            while (System.currentTimeMillis() < endTime) {
                System.out.printf("  [监控] 队列长度: %d | 已服务: %d | 总客户: %d%n",
                    customerQueue.size(), servedCustomers.get(), totalCustomers.get());
                try {
                    Thread.sleep(5000); // 每5秒监控一次
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return;
                }
            }
        }
    }
    /**
     * 获取当前时间格式化字符串
     */
    private static String getCurrentTime() {
        return String.format("%tT", new Date());
    }
    /**
     * 打印统计结果
     */
    private static void printStatistics(long startTime) {
        long totalTime = System.currentTimeMillis() - startTime;
        System.out.println("\n===== 仿真统计结果 =====");
        System.out.println("总耗时: " + totalTime / 1000 + "秒");
        System.out.println("总客户数: " + totalCustomers.get());
        System.out.println("已服务客户数: " + servedCustomers.get());
        System.out.println("未服务客户数: " + (totalCustomers.get() - servedCustomers.get()));
        if (servedCustomers.get() > 0) {
            double avgWaitingTime = totalWaitingTime.get() / 
                (1000.0 * servedCustomers.get());
            System.out.printf("平均等待时间: %.2f秒%n", avgWaitingTime);
        }
        System.out.println("最大队列长度: " + maxQueueLength.get());
    }
}

运行结果示例

===== 银行排队系统仿真开始 =====
仿真时长:30分钟
柜台数量:5
================================
[19:30:05] 柜台-1 开始服务
[19:30:05] 柜台-2 开始服务
[19:30:05] 柜台-3 开始服务
[19:30:05] 柜台-4 开始服务
[19:30:05] 柜台-5 开始服务
[19:30:06]: 客户#1到达 | 队列长度: 1
[19:30:07]: 客户#2到达 | 队列长度: 2
[19:30:07]: 柜台-1开始服务客户#1 | 等待时间: 0.00秒
[19:30:08]  [监控] 队列长度: 1 | 已服务: 1 | 总客户: 2
[19:30:08]: 客户#3到达 | 队列长度: 2
[19:30:09]: 柜台-2开始服务客户#2 | 等待时间: 0.00秒
[19:30:10]: 柜台-3开始服务客户#3 | 等待时间: 0.00秒
...

扩展版本 - 带图形界面的仿真

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.*;
/**
 * 银行排队系统 - GUI版本
 */
public class BankSimulationGUI extends JFrame {
    private JTextArea logArea;
    private JLabel statusLabel;
    private JButton startButton;
    private JButton stopButton;
    private JSpinner counterSpinner;
    private JSpinner durationSpinner;
    private volatile boolean simulationRunning = false;
    private Thread simulationThread;
    private BlockingQueue<Customer> queue = new LinkedBlockingQueue<>();
    private AtomicInteger totalCustomers = new AtomicInteger(0);
    private AtomicInteger servedCustomers = new AtomicInteger(0);
    public BankSimulationGUI() {
        setTitle("银行排队系统仿真");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        initComponents();
        layoutComponents();
    }
    private void initComponents() {
        logArea = new JTextArea();
        logArea.setEditable(false);
        logArea.setFont(new Font("Monospaced", Font.PLAIN, 12));
        statusLabel = new JLabel("状态: 就绪");
        startButton = new JButton("开始仿真");
        stopButton = new JButton("停止仿真");
        stopButton.setEnabled(false);
        counterSpinner = new JSpinner(new SpinnerNumberModel(5, 1, 10, 1));
        durationSpinner = new JSpinner(new SpinnerNumberModel(5, 1, 60, 1));
        startButton.addActionListener(e -> startSimulation());
        stopButton.addActionListener(e -> stopSimulation());
    }
    private void layoutComponents() {
        setLayout(new BorderLayout());
        // 控制面板
        JPanel controlPanel = new JPanel(new FlowLayout());
        controlPanel.add(new JLabel("柜台数:"));
        controlPanel.add(counterSpinner);
        controlPanel.add(new JLabel("仿真时长(秒):"));
        controlPanel.add(durationSpinner);
        controlPanel.add(startButton);
        controlPanel.add(stopButton);
        controlPanel.add(statusLabel);
        add(controlPanel, BorderLayout.NORTH);
        add(new JScrollPane(logArea), BorderLayout.CENTER);
    }
    private void startSimulation() {
        if (simulationRunning) return;
        simulationRunning = true;
        startButton.setEnabled(false);
        stopButton.setEnabled(true);
        statusLabel.setText("状态: 仿真进行中");
        int counters = (Integer) counterSpinner.getValue();
        int duration = (Integer) durationSpinner.getValue();
        simulationThread = new Thread(() -> runSimulation(counters, duration));
        simulationThread.start();
    }
    private void stopSimulation() {
        simulationRunning = false;
        startButton.setEnabled(true);
        stopButton.setEnabled(false);
        statusLabel.setText("状态: 已停止");
    }
    private void runSimulation(int numCounters, int durationSeconds) {
        long startTime = System.currentTimeMillis();
        long endTime = startTime + durationSeconds * 1000;
        // 创建柜台线程
        for (int i = 0; i < numCounters; i++) {
            final int counterId = i + 1;
            new Thread(() -> {
                while (simulationRunning && System.currentTimeMillis() < endTime) {
                    try {
                        Customer customer = queue.poll(500, TimeUnit.MILLISECONDS);
                        if (customer != null) {
                            appendLog(String.format("[%s] 柜台#%d开始服务客户#%d", 
                                getTime(), counterId, customer.id));
                            Thread.sleep(customer.serviceTime);
                            servedCustomers.incrementAndGet();
                            appendLog(String.format("[%s] 柜台#%d完成客户#%d | 已服务: %d", 
                                getTime(), counterId, customer.id, servedCustomers.get()));
                        }
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }, "Counter-" + i).start();
        }
        // 生成客户
        int customerId = 0;
        Random random = new Random();
        while (simulationRunning && System.currentTimeMillis() < endTime) {
            try {
                Thread.sleep(500 + random.nextInt(1500));
                Customer customer = new Customer(
                    ++customerId, 
                    System.currentTimeMillis(),
                    500 + random.nextInt(2000)
                );
                queue.offer(customer);
                totalCustomers.incrementAndGet();
                appendLog(String.format("[%s] 客户#%d到达 | 队列长度: %d", 
                    getTime(), customerId, queue.size()));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        // 等待队列清空
        appendLog("客户生成停止,等待队列清空...");
        while (!queue.isEmpty() && simulationRunning) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
        SwingUtilities.invokeLater(() -> {
            statusLabel.setText("状态: 仿真完成");
            startButton.setEnabled(true);
            stopButton.setEnabled(false);
            appendLog(String.format("仿真完成! 总客户: %d | 已服务: %d", 
                totalCustomers.get(), servedCustomers.get()));
        });
    }
    private void appendLog(String message) {
        SwingUtilities.invokeLater(() -> {
            logArea.append(message + "\n");
            logArea.setCaretPosition(logArea.getDocument().getLength());
        });
    }
    private String getTime() {
        return String.format("%tT", new Date());
    }
    static class Customer {
        final int id;
        final long arrivalTime;
        final long serviceTime;
        Customer(int id, long arrivalTime, long serviceTime) {
            this.id = id;
            this.arrivalTime = arrivalTime;
            this.serviceTime = serviceTime;
        }
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new BankSimulationGUI().setVisible(true);
        });
    }
}

仿真案例说明

核心概念:

  1. 生产者-消费者模式 - 客户生成器(生产者)和柜台服务(消费者)
  2. 线程同步 - 使用BlockingQueue实现并发安全的队列
  3. 原子变量 - AtomicInteger/AtomicLong用于并发计数
  4. 线程生命周期 - 优雅关闭和线程join

关键设计模式:

  • 并发队列:LinkedBlockingQueue作为共享数据缓冲区
  • 随机模拟:使用Random类模拟真实的到达和服务时间
  • 监控机制:实时查看系统状态
  • 统计收集:记录关键性能指标

可扩展方向:

  1. 添加VIP客户优先级队列
  2. 实现多个服务类型(存款/取款/贷款)
  3. 添加动态调整柜台数量策略
  4. 集成实时图表展示(JavaFX)
  5. 支持参数配置(通过配置文件)

这个仿真案例展示了Java多线程编程的核心技术和设计模式,可以用于教学或实际的排队系统模拟分析。

抱歉,评论功能暂时关闭!