import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
// 进程节点类
class ProcessNode {
int id;
String name;
ProcessNode left;
ProcessNode right;
int x, y; // 用于绘制的坐标
Color color;
String status; // 进程状态: READY, RUNNING, BLOCKED
int resources; // 持有的资源数量
int requestedResources; // 请求的资源数量
public ProcessNode(int id, String name) {
this.id = id;
this.name = name;
this.left = null;
this.right = null;
this.color = Color.BLUE;
this.status = "READY";
this.resources = 0;
this.requestedResources = 0;
}
}
// 资源管理器类(信号量)
class ResourceManager {
private int availableResources;
private int availableCPU; // CPU数量
private Queue<ProcessNode> blockedQueue; // 阻塞队列
private Queue<ProcessNode> readyQueue; // 就绪队列(FCFS队列)
private List<ProcessNode> runningQueue; // 运行队列
private Random random;
public ResourceManager(int initialResources) {
this.availableResources = initialResources;
this.availableCPU = 1; // 只有1个CPU
this.blockedQueue = new LinkedList<>();
this.readyQueue = new LinkedList<>(); // FCFS队列
this.runningQueue = new ArrayList<>();
this.random = new Random();
}
// 添加进程时消耗资源
public synchronized boolean addProcess(ProcessNode process) {
// P0节点不需要资源,直接添加到树中但不加入队列
if (process.id == 0) {
System.out.println("Process P0 added to tree only (no resources consumed)");
return true;
}
// 每个进程需要1个资源
int requiredResources = 1;
if (availableResources >= requiredResources) {
availableResources -= requiredResources;
process.resources += requiredResources;
// 添加到就绪队列队尾(FCFS)
readyQueue.add(process);
process.status = "READY";
process.color = Color.BLUE;
System.out.println("Process " + process.name + " added successfully. Consumed 1 resource. Available resources: " + availableResources);
// 尝试分配CPU
allocateCPU();
return true;
} else {
// 资源不足,直接进入阻塞队列队尾
blockedQueue.add(process);
process.status = "BLOCKED";
process.color = Color.RED;
System.out.println("Process " + process.name + " blocked when adding. Available resources: " + availableResources);
return false;
}
}
// 分配CPU给就绪队列中的进程(FCFS)
private synchronized void allocateCPU() {
if (availableCPU > 0 && !readyQueue.isEmpty()) {
// 有可用CPU且就绪队列不为空,从队首取进程(FCFS)
ProcessNode process = readyQueue.poll(); // 获取并移除就绪队列的第一个进程
runningQueue.add(process);
availableCPU--;
process.status = "RUNNING";
process.color = Color.GREEN;
System.out.println("CPU allocated to " + process.name + " (FCFS). Available CPU: " + availableCPU);
}
}
// P操作 - 申请资源
public synchronized boolean requestResource(ProcessNode process, int resources) {
// P0节点不参与资源申请
if (process.id == 0) {
System.out.println("Process P0 does not participate in resource requests");
return true;
}
process.requestedResources = resources;
if (availableResources >= resources) {
availableResources -= resources;
process.resources += resources;
System.out.println("Process " + process.name + " successfully requested " + resources + " resources");
return true;
} else {
// 当前进程需要阻塞
if (runningQueue.contains(process)) {
// 如果是运行中的进程,释放CPU
runningQueue.remove(process);
availableCPU++;
System.out.println("Process " + process.name + " released CPU due to resource blocking");
}
readyQueue.remove(process);
// 添加到阻塞队列队尾
if (!blockedQueue.contains(process)) {
blockedQueue.add(process);
}
process.status = "BLOCKED";
process.color = Color.RED;
System.out.println("Process " + process.name + " blocked when requesting " + resources + " resources. Available: " + availableResources);
// 释放的CPU可以分配给其他就绪进程
allocateCPU();
return false;
}
}
// V操作 - 释放资源
public synchronized void releaseResource(ProcessNode process, int resources) {
// P0节点不参与资源释放
if (process.id == 0) {
System.out.println("Process P0 does not participate in resource release");
return;
}
availableResources += resources;
process.resources -= resources;
System.out.println("Process " + process.name + " released " + resources + " resources. Now available: " + availableResources);
// 检查阻塞队列
checkBlockedQueue();
}
// 进程完成运行,释放CPU,转入就绪队列队尾
public synchronized void processCompleted(ProcessNode process) {
// P0节点不参与运行
if (process.id == 0) {
System.out.println("Process P0 does not participate in CPU running");
return;
}
if (runningQueue.contains(process)) {
// 释放CPU
runningQueue.remove(process);
availableCPU++;
System.out.println("Process " + process.name + " completed. Released CPU. Available CPU: " + availableCPU);
// 转入就绪队列队尾
readyQueue.add(process);
process.status = "READY";
process.color = Color.BLUE;
System.out.println("Process " + process.name + " moved to ready queue tail");
// 尝试分配CPU给其他就绪进程
allocateCPU();
}
// 检查阻塞队列(因为可能释放了资源)
checkBlockedQueue();
}
// 检查阻塞队列 - 优化的版本
private synchronized void checkBlockedQueue() {
if (blockedQueue.isEmpty()) {
return;
}
// 创建一个临时队列来存放仍然需要等待的进程
Queue<ProcessNode> stillBlocked = new LinkedList<>();
// 遍历阻塞队列,尝试唤醒可以运行的进程
while (!blockedQueue.isEmpty()) {
ProcessNode blockedProcess = blockedQueue.poll();
// 检查是新添加的阻塞进程还是资源请求阻塞的进程
int requiredResources = (blockedProcess.resources == 0) ? 1 : blockedProcess.requestedResources;
if (availableResources >= requiredResources) {
// 有足够资源,唤醒进程到就绪队列队尾
availableResources -= requiredResources;
blockedProcess.resources += requiredResources;
// 移动到就绪队列队尾(FCFS)
readyQueue.add(blockedProcess);
blockedProcess.status = "READY";
blockedProcess.color = Color.BLUE;
if (blockedProcess.resources == 1) {
System.out.println("Waking up new process " + blockedProcess.name + " with 1 resource, moved to ready queue tail");
} else {
System.out.println("Waking up process " + blockedProcess.name + " with " + blockedProcess.requestedResources + " resources, moved to ready queue tail");
}
} else {
// 仍然没有足够资源,保持阻塞
stillBlocked.add(blockedProcess);
}
}
// 将仍然阻塞的进程放回阻塞队列
blockedQueue = stillBlocked;
// 尝试分配CPU给新唤醒的就绪进程
allocateCPU();
}
// 节点删除时释放其资源
public synchronized void releaseAllResources(ProcessNode process) {
// P0节点没有资源
if (process.id == 0) {
System.out.println("Process P0 deleted (no resources to release)");
} else if (process.resources > 0) {
availableResources += process.resources;
System.out.println("Process " + process.name + " deleted, released all " + process.resources + " resources");
process.resources = 0;
}
// 如果是运行中的进程,释放CPU
if (runningQueue.contains(process)) {
runningQueue.remove(process);
availableCPU++;
System.out.println("Process " + process.name + " released CPU due to deletion");
}
// 从所有队列中移除该进程
readyQueue.remove(process);
runningQueue.remove(process);
blockedQueue.remove(process);
// 检查是否可以唤醒其他进程并分配CPU
checkBlockedQueue();
allocateCPU();
}
// 强制进程下CPU(用于防止进程霸占CPU)
public synchronized void forceProcessOffCPU(ProcessNode process) {
// P0节点不参与运行
if (process.id == 0) {
System.out.println("Process P0 does not participate in CPU running");
return;
}
if (runningQueue.contains(process)) {
// 释放CPU
runningQueue.remove(process);
availableCPU++;
// 随机决定进程去向:50%概率进入阻塞队列,50%概率进入就绪队列
if (random.nextBoolean()) {
// 进入阻塞队列队尾
blockedQueue.add(process);
process.status = "BLOCKED";
process.color = Color.RED;
System.out.println("Process " + process.name + " forced off CPU to blocked queue (random decision)");
} else {
// 进入就绪队列队尾
readyQueue.add(process);
process.status = "READY";
process.color = Color.BLUE;
System.out.println("Process " + process.name + " forced off CPU to ready queue tail (random decision)");
}
// 尝试分配CPU给其他就绪进程
allocateCPU();
}
}
// 运行进程下CPU后释放资源
public synchronized void releaseResourceFromRunningProcess(ProcessNode process, int resources) {
if (runningQueue.contains(process)) {
// 释放CPU
runningQueue.remove(process);
availableCPU++;
// 释放资源
availableResources += resources;
process.resources -= resources;
// 转入就绪队列队尾
readyQueue.add(process);
process.status = "READY";
process.color = Color.BLUE;
System.out.println("Process " + process.name + " released " + resources + " resources and moved to ready queue tail. Available resources: " + availableResources);
// 检查阻塞队列并分配CPU
checkBlockedQueue();
allocateCPU();
}
}
public int getAvailableResources() {
return availableResources;
}
public int getAvailableCPU() {
return availableCPU;
}
public int getBlockedCount() {
return blockedQueue.size();
}
public int getReadyCount() {
return readyQueue.size();
}
public int getRunningCount() {
return runningQueue.size();
}
public List<ProcessNode> getReadyQueue() {
return new ArrayList<>(readyQueue);
}
public List<ProcessNode> getRunningQueue() {
return new ArrayList<>(runningQueue);
}
public Queue<ProcessNode> getBlockedQueue() {
return new LinkedList<>(blockedQueue);
}
}
// 支持中文字体的二叉树面板
class BinaryTreePanel extends JPanel {
ProcessNode root;
private ResourceManager resourceManager;
private Random random;
int processId;
private Font chineseFont;
public BinaryTreePanel() {
this.root = null;
this.resourceManager = new ResourceManager(3); // 初始3个资源
this.random = new Random();
this.processId = 0; // 从0开始
// 设置支持中文的字体
chineseFont = createChineseFont();
setBackground(Color.WHITE);
setLayout(new BorderLayout());
}
// 创建支持中文的字体
private Font createChineseFont() {
String[] fontNames = {
"Microsoft YaHei", "SimHei", "SimSun", "KaiTi",
"Arial Unicode MS", "Dialog", "SansSerif"
};
for (String fontName : fontNames) {
Font font = new Font(fontName, Font.PLAIN, 12);
if (font.canDisplay('中')) {
return font;
}
}
return new Font("Dialog", Font.PLAIN, 12);
}
// 插入节点 - 修改为消耗资源
public void insertNode(int id, String name) {
ProcessNode newNode = new ProcessNode(id, name);
// 先添加到树中
root = insertRecursive(root, newNode);
// 然后尝试添加到资源管理器(P0不加入队列)
if (id != 0) {
resourceManager.addProcess(newNode);
}
calculatePositions();
repaint();
}
private ProcessNode insertRecursive(ProcessNode current, ProcessNode newNode) {
if (current == null) {
return newNode;
}
// 随机选择插入左子树或右子树
if (random.nextBoolean()) {
current.left = insertRecursive(current.left, newNode);
} else {
current.right = insertRecursive(current.right, newNode);
}
return current;
}
// 删除随机节点
public void deleteRandomNode() {
if (root == null) {
JOptionPane.showMessageDialog(this, "树为空,无法删除节点");
return;
}
ProcessNode nodeToDelete = getRandomNode(root);
if (nodeToDelete != null) {
deleteNodeAndChildren(nodeToDelete.id);
}
}
// 删除指定ID的节点及其所有子节点
public void deleteNodeAndChildren(int id) {
if (root == null) {
JOptionPane.showMessageDialog(this, "树为空,无法删除节点");
return;
}
ProcessNode nodeToDelete = findNodeById(root, id);
if (nodeToDelete != null) {
// 递归释放该节点及其所有子节点的资源
releaseNodeAndChildrenResources(nodeToDelete);
// 从树中删除该节点及其所有子节点
root = deleteNodeAndChildrenRecursive(root, nodeToDelete);
calculatePositions();
repaint();
System.out.println("删除节点及其子节点: " + nodeToDelete.name + " (ID: " + id + ")");
JOptionPane.showMessageDialog(this, "成功删除节点及其子节点: " + nodeToDelete.name + " (ID: " + id + ")");
} else {
JOptionPane.showMessageDialog(this, "未找到ID为 " + id + " 的节点");
}
}
// 递归释放节点及其所有子节点的资源
private void releaseNodeAndChildrenResources(ProcessNode node) {
if (node == null) return;
// 释放当前节点的资源
resourceManager.releaseAllResources(node);
// 递归释放左子树资源
releaseNodeAndChildrenResources(node.left);
// 递归释放右子树资源
releaseNodeAndChildrenResources(node.right);
}
// 递归删除节点及其所有子节点
private ProcessNode deleteNodeAndChildrenRecursive(ProcessNode root, ProcessNode nodeToDelete) {
if (root == null) return null;
if (root == nodeToDelete) {
// 返回null表示删除整个子树
return null;
}
// 递归在左右子树中查找并删除
root.left = deleteNodeAndChildrenRecursive(root.left, nodeToDelete);
root.right = deleteNodeAndChildrenRecursive(root.right, nodeToDelete);
return root;
}
// 根据ID查找节点
private ProcessNode findNodeById(ProcessNode node, int id) {
if (node == null) {
return null;
}
if (node.id == id) {
return node;
}
ProcessNode leftResult = findNodeById(node.left, id);
if (leftResult != null) {
return leftResult;
}
return findNodeById(node.right, id);
}
// 随机生成节点
public void generateRandomNodes(int count) {
for (int i = 0; i < count; i++) {
// 进程名称与ID对应,例如ID=0 -> P0, ID=1 -> P1
insertNode(processId, "P" + processId);
processId++; // 插入后再递增
}
calculatePositions();
repaint();
}
// 清空所有节点
public void clearAllNodes() {
// 释放所有节点的资源
if (root != null) {
releaseAllResourcesRecursive(root);
}
root = null;
processId = 0; // 重置为0
repaint();
}
private void releaseAllResourcesRecursive(ProcessNode node) {
if (node == null) return;
resourceManager.releaseAllResources(node);
releaseAllResourcesRecursive(node.left);
releaseAllResourcesRecursive(node.right);
}
private int countNodes(ProcessNode node) {
if (node == null) return 0;
return 1 + countNodes(node.left) + countNodes(node.right);
}
// 获取所有节点的ID列表(用于用户选择)
public List<Integer> getAllNodeIds() {
List<Integer> ids = new ArrayList<>();
collectNodeIds(root, ids);
return ids;
}
private void collectNodeIds(ProcessNode node, List<Integer> ids) {
if (node == null) return;
ids.add(node.id);
collectNodeIds(node.left, ids);
collectNodeIds(node.right, ids);
}
// 计算节点位置
private void calculatePositions() {
if (root == null) return;
int levelHeight = 80;
int startX = getWidth() / 2;
int startY = 120;
calculatePositionRecursive(root, startX, startY, Math.max(200, getWidth() / 4), levelHeight, 0);
}
private void calculatePositionRecursive(ProcessNode node, int x, int y, int offsetX, int levelHeight, int level) {
if (node == null) return;
node.x = x;
node.y = y;
if (node.left != null) {
calculatePositionRecursive(node.left, x - offsetX, y + levelHeight, offsetX / 2, levelHeight, level + 1);
}
if (node.right != null) {
calculatePositionRecursive(node.right, x + offsetX, y + levelHeight, offsetX / 2, levelHeight, level + 1);
}
}
private int getHeight(ProcessNode node) {
if (node == null) return 0;
return 1 + Math.max(getHeight(node.left), getHeight(node.right));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 绘制资源信息和队列状态
drawResourceAndQueueInfo(g2d);
// 绘制树
if (root != null) {
drawTree(g2d, root);
}
// 绘制队列可视化
drawQueueVisualization(g2d);
}
private void drawResourceAndQueueInfo(Graphics2D g2d) {
g2d.setColor(Color.BLACK);
g2d.setFont(chineseFont.deriveFont(Font.BOLD, 16));
// 资源信息
g2d.drawString("可用资源: " + resourceManager.getAvailableResources(), 20, 30);
g2d.drawString("可用CPU: " + resourceManager.getAvailableCPU(), 20, 55);
// 队列统计信息
g2d.setFont(chineseFont.deriveFont(Font.BOLD, 14));
g2d.setColor(Color.BLUE);
g2d.drawString("就绪队列: " + resourceManager.getReadyCount(), 200, 30);
g2d.setColor(Color.GREEN);
g2d.drawString("运行队列: " + resourceManager.getRunningCount(), 350, 30);
g2d.setColor(Color.RED);
g2d.drawString("阻塞队列: " + resourceManager.getBlockedCount(), 500, 30);
g2d.setColor(Color.BLACK);
g2d.drawString("总进程数: " + (root != null ? countNodes(root) : 0), 650, 30);
// 显示下一个进程ID
g2d.drawString("下一个进程ID: " + processId, 800, 30);
}
private void drawTree(Graphics2D g2d, ProcessNode node) {
if (node == null) return;
// 绘制连接线
if (node.left != null) {
g2d.setColor(Color.GRAY);
g2d.drawLine(node.x, node.y, node.left.x, node.left.y);
drawTree(g2d, node.left);
}
if (node.right != null) {
g2d.setColor(Color.GRAY);
g2d.drawLine(node.x, node.y, node.right.x, node.right.y);
drawTree(g2d, node.right);
}
// 绘制节点
g2d.setColor(node.color);
g2d.fillOval(node.x - 25, node.y - 25, 50, 50);
g2d.setColor(Color.WHITE);
g2d.setFont(chineseFont.deriveFont(Font.BOLD, 12));
// 绘制节点信息
String nodeInfo = node.name;
FontMetrics fm = g2d.getFontMetrics();
int textWidth = fm.stringWidth(nodeInfo);
g2d.drawString(nodeInfo, node.x - textWidth / 2, node.y - 8);
// 绘制状态和资源
g2d.setFont(chineseFont.deriveFont(Font.PLAIN, 10));
String statusInfo = node.status + "(" + node.resources + ")";
textWidth = fm.stringWidth(statusInfo);
g2d.drawString(statusInfo, node.x - textWidth / 2, node.y + 5);
// 绘制ID
String idInfo = "ID:" + node.id;
textWidth = fm.stringWidth(idInfo);
g2d.drawString(idInfo, node.x - textWidth / 2, node.y + 18);
}
private void drawQueueVisualization(Graphics2D g2d) {
int panelHeight = getHeight();
int queueStartY = panelHeight - 150;
int boxHeight = 30;
int boxWidth = 60;
int spacing = 10;
// 绘制就绪队列
g2d.setColor(Color.BLUE);
g2d.setFont(chineseFont.deriveFont(Font.BOLD, 14));
g2d.drawString("就绪队列 (" + resourceManager.getReadyCount() + "):", 50, queueStartY - 10);
int xPos = 50;
for (ProcessNode process : resourceManager.getReadyQueue()) {
g2d.setColor(Color.BLUE);
g2d.fillRect(xPos, queueStartY, boxWidth, boxHeight);
g2d.setColor(Color.WHITE);
g2d.drawString(process.name, xPos + 15, queueStartY + 20);
xPos += boxWidth + spacing;
}
// 绘制运行队列
g2d.setColor(Color.GREEN);
g2d.drawString("运行队列 (" + resourceManager.getRunningCount() + "):", 50, queueStartY + 50);
xPos = 50;
for (ProcessNode process : resourceManager.getRunningQueue()) {
g2d.setColor(Color.GREEN);
g2d.fillRect(xPos, queueStartY + 60, boxWidth, boxHeight);
g2d.setColor(Color.WHITE);
g2d.drawString(process.name, xPos + 15, queueStartY + 80);
xPos += boxWidth + spacing;
}
// 绘制阻塞队列
g2d.setColor(Color.RED);
g2d.drawString("阻塞队列 (" + resourceManager.getBlockedCount() + "):", 50, queueStartY + 110);
xPos = 50;
for (ProcessNode process : resourceManager.getBlockedQueue()) {
g2d.setColor(Color.RED);
g2d.fillRect(xPos, queueStartY + 120, boxWidth, boxHeight);
g2d.setColor(Color.WHITE);
g2d.drawString(process.name, xPos + 15, queueStartY + 140);
xPos += boxWidth + spacing;
}
}
// 随机选择一个节点进行操作
public void performRandomOperation() {
if (root == null) {
JOptionPane.showMessageDialog(this, "树为空,请先添加节点");
return;
}
ProcessNode randomNode = getRandomNode(root);
if (randomNode == null) return;
// P0节点不参与操作
if (randomNode.id == 0) {
System.out.println("P0节点不参与资源操作");
return;
}
int operation = random.nextInt(4); // 0: 申请资源, 1: 释放资源, 2: 完成运行, 3: 下CPU释放资源
if (operation == 0) {
// 申请1-3个资源
int requestedResources = random.nextInt(3) + 1;
resourceManager.requestResource(randomNode, requestedResources);
} else if (operation == 1) {
// 释放资源(如果有的话)
if (randomNode.resources > 0) {
int releasedResources = Math.min(randomNode.resources, random.nextInt(randomNode.resources) + 1);
resourceManager.releaseResource(randomNode, releasedResources);
} else {
// 如果没有资源,就申请资源
int requestedResources = random.nextInt(3) + 1;
resourceManager.requestResource(randomNode, requestedResources);
}
} else if (operation == 2) {
// 完成运行(如果是运行中的进程)
if (randomNode.status.equals("RUNNING")) {
resourceManager.processCompleted(randomNode);
} else {
// 如果不是运行中的进程,就申请资源
int requestedResources = random.nextInt(3) + 1;
resourceManager.requestResource(randomNode, requestedResources);
}
} else {
// 运行进程下CPU并释放资源
if (randomNode.status.equals("RUNNING") && randomNode.resources > 0) {
int releasedResources = Math.min(randomNode.resources, random.nextInt(randomNode.resources) + 1);
resourceManager.releaseResourceFromRunningProcess(randomNode, releasedResources);
} else if (randomNode.status.equals("RUNNING")) {
// 如果没有资源,就完成运行
resourceManager.processCompleted(randomNode);
} else {
// 如果不是运行中的进程,就申请资源
int requestedResources = random.nextInt(3) + 1;
resourceManager.requestResource(randomNode, requestedResources);
}
}
repaint();
}
private ProcessNode getRandomNode(ProcessNode node) {
if (node == null) return null;
// 使用BFS随机选择一个节点
Queue<ProcessNode> queue = new LinkedList<>();
queue.add(node);
ProcessNode result = null;
int count = 0;
while (!queue.isEmpty()) {
ProcessNode current = queue.poll();
count++;
// 每个节点有相等的概率被选中
if (random.nextDouble() < 1.0 / count) {
result = current;
}
if (current.left != null) queue.add(current.left);
if (current.right != null) queue.add(current.right);
}
return result != null ? result : node;
}
@Override
public Dimension getPreferredSize() {
return new Dimension(1000, 800);
}
}
// 主界面
public class ProcessBinaryTreeVisualization extends JFrame {
private BinaryTreePanel treePanel;
private JButton addProcessButton;
private JButton addRandomButton;
private JButton deleteRandomNodeButton;
private JButton deleteSpecificNodeButton;
private JButton operateButton;
private JButton autoOperateButton;
private JButton clearButton;
private Timer autoTimer;
public ProcessBinaryTreeVisualization() {
setTitle("进程二叉树可视化与PV操作模拟 - 改进调度算法 (P0不参与队列)");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// 创建树面板
treePanel = new BinaryTreePanel();
add(treePanel, BorderLayout.CENTER);
// 创建控制面板
JPanel controlPanel = createControlPanel();
add(controlPanel, BorderLayout.SOUTH);
// 创建信息面板
JPanel infoPanel = createInfoPanel();
add(infoPanel, BorderLayout.NORTH);
pack();
setLocationRelativeTo(null);
setSize(1000, 800);
}
private JPanel createControlPanel() {
JPanel controlPanel = new JPanel(new FlowLayout());
// 使用支持中文的字体设置按钮
Font buttonFont = createChineseFont().deriveFont(Font.PLAIN, 14);
addProcessButton = new JButton("添加单个进程");
addRandomButton = new JButton("随机生成5个进程");
deleteRandomNodeButton = new JButton("删除随机节点");
deleteSpecificNodeButton = new JButton("删除指定节点");
operateButton = new JButton("执行PV操作");
autoOperateButton = new JButton("开始自动操作");
clearButton = new JButton("清空所有节点");
// 设置按钮字体
addProcessButton.setFont(buttonFont);
addRandomButton.setFont(buttonFont);
deleteRandomNodeButton.setFont(buttonFont);
deleteSpecificNodeButton.setFont(buttonFont);
operateButton.setFont(buttonFont);
autoOperateButton.setFont(buttonFont);
clearButton.setFont(buttonFont);
controlPanel.add(addProcessButton);
controlPanel.add(addRandomButton);
controlPanel.add(deleteRandomNodeButton);
controlPanel.add(deleteSpecificNodeButton);
controlPanel.add(operateButton);
controlPanel.add(autoOperateButton);
controlPanel.add(clearButton);
// 添加事件监听器
addProcessButton.addActionListener(e -> {
// 进程名称与ID对应,例如ID=0 -> P0, ID=1 -> P1
treePanel.insertNode(treePanel.processId, "P" + treePanel.processId);
treePanel.processId++; // 插入后再递增
});
addRandomButton.addActionListener(e -> treePanel.generateRandomNodes(5));
deleteRandomNodeButton.addActionListener(e -> treePanel.deleteRandomNode());
deleteSpecificNodeButton.addActionListener(e -> deleteSpecificNode());
operateButton.addActionListener(e -> treePanel.performRandomOperation());
autoOperateButton.addActionListener(e -> toggleAutoOperation());
clearButton.addActionListener(e -> treePanel.clearAllNodes());
return controlPanel;
}
// 删除指定节点
private void deleteSpecificNode() {
if (treePanel.root == null) {
JOptionPane.showMessageDialog(this, "树为空,无法删除节点");
return;
}
// 获取所有可用的节点ID
List<Integer> availableIds = treePanel.getAllNodeIds();
if (availableIds.isEmpty()) {
JOptionPane.showMessageDialog(this, "没有可删除的节点");
return;
}
// 创建选择对话框
String[] options = new String[availableIds.size()];
for (int i = 0; i < availableIds.size(); i++) {
options[i] = "P" + availableIds.get(i) + " (ID: " + availableIds.get(i) + ")";
}
String selected = (String) JOptionPane.showInputDialog(
this,
"选择要删除的节点:",
"删除指定节点",
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]
);
if (selected != null) {
// 从选择中提取ID
int id = Integer.parseInt(selected.substring(1, selected.indexOf(" ")));
treePanel.deleteNodeAndChildren(id);
}
}
private JPanel createInfoPanel() {
JPanel infoPanel = new JPanel();
infoPanel.setBackground(new Color(240, 240, 240));
infoPanel.setBorder(BorderFactory.createTitledBorder("状态说明"));
// 使用支持中文的字体
Font infoFont = createChineseFont().deriveFont(Font.PLAIN, 14);
JLabel infoLabel = new JLabel(
"<html>" +
"● <font color='blue'>蓝色</font>: 就绪状态(READY) | " +
"● <font color='green'>绿色</font>: 运行状态(RUNNING) | " +
"● <font color='red'>红色</font>: 阻塞状态(BLOCKED) | " +
"节点显示: 进程名(状态)资源数 | " +
"<b>P0节点特殊规则</b>: 不消耗资源、不参与队列、不运行 | " +
"初始资源: 3个,CPU: 1个 | " +
"每个进程(P1开始)创建需要1个资源 | " +
"<b>FCFS调度</b>: 就绪队列队首→运行队列 | " +
"<b>进程流转</b>: 运行完成→就绪队列队尾 | " +
"<b>资源分配</b>: 运行进程释放资源→阻塞队列队首→就绪队列队尾 | " +
"就绪态不能直接转入阻塞态" +
"</html>"
);
infoLabel.setFont(infoFont);
infoPanel.add(infoLabel);
return infoPanel;
}
// 创建支持中文的字体
private Font createChineseFont() {
String[] fontNames = {
"Microsoft YaHei", "SimHei", "SimSun", "KaiTi",
"Arial Unicode MS", "Dialog"
};
for (String fontName : fontNames) {
Font font = new Font(fontName, Font.PLAIN, 12);
if (font.canDisplay('中')) {
return font;
}
}
return new Font("Dialog", Font.PLAIN, 12);
}
private void toggleAutoOperation() {
if (autoTimer == null) {
autoTimer = new Timer(1500, e -> treePanel.performRandomOperation());
autoTimer.start();
autoOperateButton.setText("停止自动操作");
addProcessButton.setEnabled(false);
addRandomButton.setEnabled(false);
deleteRandomNodeButton.setEnabled(false);
deleteSpecificNodeButton.setEnabled(false);
operateButton.setEnabled(false);
} else {
autoTimer.stop();
autoTimer = null;
autoOperateButton.setText("开始自动操作");
addProcessButton.setEnabled(true);
addRandomButton.setEnabled(true);
deleteRandomNodeButton.setEnabled(true);
deleteSpecificNodeButton.setEnabled(true);
operateButton.setEnabled(true);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
new ProcessBinaryTreeVisualization().setVisible(true);
});
}
}修改代码,第一:三个队列关系,就绪队列必须等待进入运行队列,运行队列进入阻塞(进入阻塞时,必须让资源数加一)或者就绪队列(阻塞队列不变,就绪队列队首进入运行态),以此类推。第二:修改资源数为五个,CPU个数为2
最新发布