我正在尝试实施循环调度算法。但到目前为止我所做的代码只考虑了突发时间。我也需要考虑这个过程的到达时间。我有一个time_chart数组,我用它来存储当前正在执行的进程的编号。但是如果当前没有进程正在执行(即如果所选进程已完成执行并且下一个进程尚未到达。),则应将值0插入time_chart数组中。
我将爆发时间和到达时间存储在2D数组中:
//proc[][0] is the AT array
//proc[][1] is the BT array
和变量q中的时间量子。以下是我的代码:
int time_chart[] = new int[total_time];
int sel_proc = 1;
int current_q = 0;
for (int k = 0; k < total_time; k++) {
//Assign selected process to current time in the Chart
time_chart[k] = sel_proc;
//Decrement Remaining Time of selected process by 1 since it has been assigned the CPU for 1 unit of time
proc[sel_proc - 1][1]--;
//Updating value of sel_proc for next iteration
current_q++;
if (current_q == q || proc[sel_proc - 1][1] == 0)//If Time slice has expired or the current process has completed execution
{
current_q = 0;
//This will select the next valid value for sel_proc
for (int j = 1; j <= n; j++) {
sel_proc++;
if (sel_proc == (n + 1)) {
sel_proc = 1;
}
if (proc[sel_proc - 1][1] != 0) {
break;
}
}
}
}
// print timeline for testing
for (i = 0; i < total_time; i++) {
System.out.println("Time " + i + ": " + time_chart[i]);
}
目前它将选择下一个进程,即使它尚未到达。因此,我需要检查下一个进程是否已到达。我尝试使用proc[sel_proc][0] <= k
来检查这一点,但似乎没有用。我的意思是我没有得到任何输出。我想不出另一种检查下一个过程是否到来的方法。如果下一个进程没有到达,我如何检查并将值0放入数组?
答案 0 :(得分:2)
虽然您可以仅使用数组来完成此操作,但如果您创建一个类结构来存储流程信息并使用两个Queues
,则可能会更容易找到逻辑。第一个Queue
是按到达时间排序的进程列表,第二个Queue
是当前正在执行的进程。
你可以建模你按照这些方式处理某些事情
private static class Process {
public final int id;
public final int burstTime;
public final int arrivalTime;
public int executionTime;
public Process(int id, int burstTime, int arrivalTime) {
super();
this.id = id;
this.burstTime = burstTime;
this.arrivalTime = arrivalTime;
}
}
然后创建一个队列调用未调度的进程(或者看似合适的进程)并将进程添加到按到达时间排序的队列中。 Queue<Process> = new LinkedList<>()
现在,在您的循环中,每次只检查队列的头部并查看进程是否正确。到达时间等于或大于当前时间。如果它从队列中删除它并将其添加到调度程序队列的头部。 LinkedList<Process> = new LinkedList<>()
始终从调度程序队列中删除头部进程并更新进程的执行时间。确保不要超过突发时间,即执行时间总是通过量子OR burstTime - executionTime增加,具体取决于哪个更小。更新后,如果执行时间小于burstTime,则将进程添加回调度程序队列。
请记住,如果过程中的剩余时间小于量子,则当前时间不会因量子而增加。
答案 1 :(得分:1)
如果不是单个int
跟踪当前正在运行的进程,则使用所有列表,这个问题要简单得多。一个很好的选择是保持一个有序的列表,其中正在运行的进程处于最前面,其他的按照它们将来应该运行的顺序。然后,您始终可以通过旋转列表来运行下一个进程。更新每个量程的列表很简单。使所有这些选项变得简单的Java集合称为Deque
。
这样的事情:
Deque<Integer> running = new ArrayDeque<>();
for (int quantum = 0; quantum < totalDuration; ++quantum) {
// Add new arrivals to the list of running processes.
// Note that if the processes are pre-sorted by arrival time,
// this loop can be made more efficient. This assumes no sorting.
for (int process = 1; process <= processCount; ++process) {
if (arrivalTime[process] == quantum)
running.addLast(process); // Use addFirst if new procs should run immediately.
}
if (running.isEmpty())
timeChart[quantum] = 0; // Nothing to run
else {
// Select the process now at the head.
int selectedProcess = running.getFirst();
// Decrement the running process's burst time. If it's done, remove
// it from the running list.
if (--burstTime[selectedProcess] == 0)
running.removeFirst();
// Record the run for this quantum.
timeChart[quantum] = selectedProcess;
// Rotate the previous head to the tail of the list for next quantum.
if (running.size() > 1)
running.addLast(running.removeFirst());
}
}
注意我使用了更合理的名称和Java约定。您选择的名称和数据类型有点可怕。正如其他人所说,在class
中对进程的到达和突发时间进行分组仍然会更好。
答案 2 :(得分:0)
实际上,您应该看到该过程的到达时间是否小于或等于下一个即将到来的时间。所以,你应该检查proc[sel_proc][0] <= k + 1
。特别是,你应该做的唯一改变是你的if而不是
if (proc[sel_proc - 1][1] != 0) {
break;
}
应该变为:(如果剩余的突发时间不为零且其到达时间在下一次之前或之前相等,即k + 1)
if (proc[sel_proc - 1][1] != 0 && proc[sel_proc][0] <= k + 1) {
break;
}
更重要的是,请确保您的上一个有效时间单位是total_time - 1而不是total_time本身。此外,您的抵达时间是0还是1,这些都是您需要注意的极端情况。
答案 3 :(得分:0)
您计划使用算法安排什么?除了实现操作系统之外,我从来没有听说过有时间切片的人。
时间切片在操作系统级别工作,因为操作系统可以选择它想在CPU上运行哪些(合格的)进程/线程,并且因为操作系统基本上可以在任何指令处停止线程并将CPU注册表刷新到缓存。如果每个任务可以分解为非常小的工作单元('CPU'指令),则此原则仅适用于代码。这样,如果你有100个任务,每个包含100个单元,4个处理器核心,你可以实现自己的时间切片算法(但我不推荐它)。
传统上,如果你有多个并发任务,你可以使用一个线程池,其线程数等于CPU核心数(或者任务有IO的更多),你只需在任务到达时对这些任务进行排队,然后让操作系统担心时间切片。