返回
Java绘制最短作业优先抢占式算法甘特图
java
2024-10-05 02:24:43
使用Java绘制最短作业优先抢占式算法的甘特图
在操作系统课程中,我们经常会遇到各种进程调度算法,其中最短作业优先(SJF)抢占式算法以其高效性而备受关注。为了更直观地理解SJF算法的运作方式,我们可以借助甘特图进行可视化。本文将介绍如何使用Java语言绘制甘特图,清晰地展现SJF抢占式算法的进程调度过程。
进程调度与甘特图
首先,我们需要明确SJF抢占式算法的基本原理:当一个新的进程到达时,如果它的执行时间比当前正在执行的进程短,则会抢占CPU,优先执行。这种调度方式可以最大程度地减少平均等待时间。
甘特图则是一种以图形方式表示进程调度过程的工具。它通常由一个水平时间轴和一系列表示进程执行时间段的矩形组成。通过观察甘特图,我们可以清晰地了解每个进程的开始时间、结束时间以及CPU的占用情况。
Java实现
数据结构
为了表示进程信息,我们可以创建一个名为Process
的类,包含以下属性:
id
:进程IDarrivalTime
:到达时间burstTime
:执行时间startTime
:开始时间completionTime
:完成时间
class Process {
int id;
double arrivalTime;
double burstTime;
double startTime;
double completionTime;
public Process(int id, double arrivalTime, double burstTime) {
this.id = id;
this.arrivalTime = arrivalTime;
this.burstTime = burstTime;
}
}
SJF算法实现
接下来,我们需要实现SJF抢占式算法的核心逻辑。可以使用一个优先队列来维护待执行的进程,并根据执行时间进行排序。当一个新的进程到达时,将其插入队列;当CPU空闲时,从队列中取出执行时间最短的进程执行。
import java.util.PriorityQueue;
import java.util.Comparator;
import java.util.List;
import java.util.ArrayList;
// ... (其他代码)
public List<Process> scheduleSJF(List<Process> processes) {
PriorityQueue<Process> queue = new PriorityQueue<>(Comparator.comparingDouble(p -> p.burstTime));
double currentTime = 0;
int completedProcesses = 0;
while (completedProcesses < processes.size()) {
// 将到达的进程添加到队列
for (Process p : processes) {
if (p.arrivalTime <= currentTime && p.startTime == 0) {
queue.add(p);
}
}
// 如果队列为空,则推进时间
if (queue.isEmpty()) {
currentTime = processes.stream()
.filter(p -> p.arrivalTime > currentTime)
.mapToDouble(p -> p.arrivalTime)
.min()
.orElse(currentTime);
continue;
}
// 取出执行时间最短的进程
Process currentProcess = queue.poll();
currentProcess.startTime = currentTime;
currentTime += currentProcess.burstTime;
currentProcess.completionTime = currentTime;
completedProcesses++;
// 检查是否有进程在当前进程执行期间到达并需要抢占
for (Process p : processes) {
if (p.arrivalTime > currentProcess.startTime && p.arrivalTime < currentProcess.completionTime && p.startTime == 0) {
// 将当前进程剩余时间重新加入队列
double remainingTime = currentProcess.completionTime - p.arrivalTime;
currentProcess.burstTime = remainingTime;
currentProcess.completionTime = 0;
queue.add(currentProcess);
// 更新当前时间
currentTime = p.arrivalTime;
break;
}
}
}
return processes;
}
甘特图绘制
最后,我们可以使用Java的图形库(例如Swing或JavaFX)绘制甘特图。以下是一个使用Swing绘制甘特图的示例代码:
// ... (其他代码)
import javax.swing.*;
import java.awt.*;
public class GanttChart extends JPanel {
private List<Process> processes;
public GanttChart(List<Process> processes) {
this.processes = processes;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int chartWidth = getWidth();
int chartHeight = getHeight();
double maxCompletionTime = processes.stream().mapToDouble(p -> p.completionTime).max().orElse(0);
// 绘制时间轴
g.drawLine(0, chartHeight / 2, chartWidth, chartHeight / 2);
for (double i = 0; i <= maxCompletionTime; i++) {
int x = (int) (i / maxCompletionTime * chartWidth);
g.drawLine(x, chartHeight / 2 - 5, x, chartHeight / 2 + 5);
g.drawString(String.format("%.1f", i), x - 10, chartHeight / 2 + 20);
}
// 绘制进程矩形
Random random = new Random();
for (Process p : processes) {
int x = (int) (p.startTime / maxCompletionTime * chartWidth);
int width = (int) (p.burstTime / maxCompletionTime * chartWidth);
Color color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
g.setColor(color);
g.fillRect(x, chartHeight / 2 - 20, width, 40);
g.setColor(Color.BLACK);
g.drawString("P" + p.id, x + width / 2 - 5, chartHeight / 2);
}
}
public static void main(String[] args) {
// 创建一些示例进程
List<Process> processes = new ArrayList<>();
processes.add(new Process(1, 0, 5));
processes.add(new Process(2, 1, 3));
processes.add(new Process(3, 2, 2));
processes.add(new Process(4, 4, 4));
// 执行SJF抢占式算法
List<Process> scheduledProcesses = new GanttChart().scheduleSJF(processes);
// 创建甘特图窗口
JFrame frame = new JFrame("SJF Preemptive Gantt Chart");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 300);
frame.add(new GanttChart(scheduledProcesses));
frame.setVisible(true);
}
}
常见问题
-
如何处理相同到达时间的进程?
- 可以根据进程ID或其他规则进行排序,确保调度顺序的确定性。
-
如何处理进程的I/O操作?
- 可以将I/O操作视为一个独立的进程,并在甘特图中进行表示。
-
如何优化甘特图的绘制效率?
- 可以使用缓存机制或其他图形优化技术,提高绘制速度。
-
如何实现甘特图的交互功能?
- 可以使用鼠标事件监听器,例如点击进程矩形显示详细信息。
-
如何将甘特图导出为图片?
- 可以使用Java的图像处理库,例如ImageIO,将甘特图保存为PNG或JPEG格式。
通过本文的介绍,我们了解了如何使用Java绘制甘特图,并以SJF抢占式算法为例,展示了进程调度的可视化过程。希望本文能够帮助读者更好地理解进程调度算法,并掌握使用Java进行图形化编程的基本方法。