本文目录导读:

我为您提供一个完整的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);
});
}
}
仿真案例说明
核心概念:
- 生产者-消费者模式 - 客户生成器(生产者)和柜台服务(消费者)
- 线程同步 - 使用BlockingQueue实现并发安全的队列
- 原子变量 - AtomicInteger/AtomicLong用于并发计数
- 线程生命周期 - 优雅关闭和线程join
关键设计模式:
- 并发队列:LinkedBlockingQueue作为共享数据缓冲区
- 随机模拟:使用Random类模拟真实的到达和服务时间
- 监控机制:实时查看系统状态
- 统计收集:记录关键性能指标
可扩展方向:
- 添加VIP客户优先级队列
- 实现多个服务类型(存款/取款/贷款)
- 添加动态调整柜台数量策略
- 集成实时图表展示(JavaFX)
- 支持参数配置(通过配置文件)
这个仿真案例展示了Java多线程编程的核心技术和设计模式,可以用于教学或实际的排队系统模拟分析。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播