CPU scheduling is the process of selecting a process from the queue of processes in the ready state and allocating the CPU to it. The primary goal of CPU scheduling is to make sure that the CPU is utilized effectively and efficiently. There are several scheduling algorithms available to manage the CPU scheduling, and one of them is the Shortest Job First (SJF) algorithm.
The SJF algorithm selects the process with the shortest burst time from the ready queue to allocate the CPU to it. This algorithm is suitable for systems where the job sizes are known beforehand. SJF scheduling algorithm can be of two types:
- Non-preemptive SJF: Once a process is assigned to the CPU, it runs until it completes its execution or goes into the waiting state.
- Preemptive SJF: The process with the shortest burst time can be interrupted by another process with even shorter burst time.
Let’s take an example to explain SJF scheduling algorithm. We have four processes with their burst times as follows:
| Process | Burst Time |
|---|---|
| P1 | 6 |
| P2 | 8 |
| P3 | 7 |
| P4 | 3 |
Suppose we have a non-preemptive SJF scheduling algorithm, and all the processes arrive at the same time. The Gantt chart below shows the sequence in which the processes will be executed.
| P4 | P1 | P3 | P2 |
Here, the process P4 will be executed first because it has the shortest burst time. After P4 completes its execution, P1 with the next shortest burst time will be executed, followed by P3 and then P2.
In case we have a preemptive SJF scheduling algorithm, the Gantt chart will look like the following:
| P4 | P1 | P4 | P3 | P4 | P2 |
Here, the process P4 will be executed first because it has the shortest burst time. While P4 is running, P1 arrives with a shorter burst time, so P4 is preempted, and P1 starts executing. After P1 completes its execution, P4 resumes its execution, followed by P3 and then P2.
data class Process(val id: Int, val arrivalTime: Int, var burstTime: Int)
fun main() {
val processes = listOf(
Process(1, 3, 1),
Process(2, 1, 4),
Process(3, 4, 2),
Process(4, 0, 6),
Process(5 ,2, 3)
)
sjf(processes)
}
fun sjf(processes: List<Process>) {
val n = processes.size
val burst = processes.map { it.burstTime }.toMutableList()
val remainingTime = IntArray(n) { burst[it] }
val completionTime = IntArray(n)
val waitingTime = IntArray(n)
val turnaroundTime = IntArray(n)
var time = 0
var minBurst = Int.MAX_VALUE
var shortest = -1
var check = false
var finished = 0
while (finished != n) {
for (i in 0 until n) {
if (processes[i].arrivalTime <= time && remainingTime[i] < minBurst && remainingTime[i] > 0) {
minBurst = remainingTime[i]
shortest = i
check = true
}
}
if (!check) {
time++
continue
}
remainingTime[shortest]--
minBurst = remainingTime[shortest]
if (minBurst == 0) {
minBurst = Int.MAX_VALUE
}
if (remainingTime[shortest] == 0) {
finished++
completionTime[shortest] = time + 1
turnaroundTime[shortest] = completionTime[shortest] - processes[shortest].arrivalTime
waitingTime[shortest] = turnaroundTime[shortest] - processes[shortest].burstTime
if (waitingTime[shortest] < 0) {
waitingTime[shortest] = 0
}
}
time++
}
val totalWaitingTime = waitingTime.sum()
val averageWaitingTime = totalWaitingTime.toFloat() / n
val totalTurnaroundTime = turnaroundTime.sum()
val averageTurnaroundTime = totalTurnaroundTime.toFloat() / n
println("SJF Scheduling:")
println("Process\t Arrival Burst\t Completion\t Waiting\t Turnaround")
for (i in 0 until n) {
println("${processes[i].id}\t ${processes[i].arrivalTime}\t ${processes[i].burstTime}\t ${completionTime[i]}\t\t ${waitingTime[i]}\t\t ${turnaroundTime[i]}")
}
println("Average waiting time: $averageWaitingTime")
println("Average turnaround time: $averageTurnaroundTime")
}- Define a
data classnamedProcessthat hasid,arrivalTime, andburstTimeas properties. Theidis an integer that identifies the process,arrivalTimeis the time at which the process arrives in the ready queue, andburstTimeis the amount of CPU time required by the process. - In the
mainfunction, create a list ofProcessobjects with differentid,arrivalTime, andburstTimevalues. - Define the
sjffunction that takes a list ofProcessobjects as input. - Get the number of processes from the input list.
- Create a mutable list
burstthat contains the burst times of all processes. - Create an integer array
remainingTimethat initially contains the burst time of each process. - Create three integer arrays
completionTime,waitingTime, andturnaroundTimeto store the completion time, waiting time, and turnaround time of each process. - Initialize the variables
time,minBurst,shortest,check, andfinishedto 0,Int.MAX_VALUE, -1,false, and 0 respectively. - Enter a
whileloop that continues until all processes have been executed. - Inside the loop, use a
forloop to iterate through all processes. - Check if a process has arrived and has remaining burst time less than the current minimum burst time. If yes, update the
minBurstandshortestvariables to track the process with the shortest remaining burst time. - Set the
checkvariable totrueif a process has been found. - If no process has been found, increment the
timevariable by 1 and continue the loop. - If a process has been found, decrement its remaining burst time by 1.
- If the remaining burst time of the current process is 0, update the
finishedvariable to track the number of completed processes. - Set the
completionTimeof the current process totime + 1. - Calculate the
turnaroundTimeof the current process by subtracting itsarrivalTimefrom itscompletionTime. - Calculate the
waitingTimeof the current process by subtracting itsburstTimefrom itsturnaroundTime. - If the
waitingTimeof the current process is negative, set it to 0. - Update the
minBurstvariable to find the next process with the shortest remaining burst time. - Increment the
timevariable by 1 and continue the loop. - After the loop, calculate the total waiting time and average waiting time of all processes.
- Calculate the total turnaround time and average turnaround time of all processes.
- Print the results of the SJF scheduling algorithm along with the average waiting time and average turnaround time.
Output :
SJF Scheduling:
Process Arrival Burst Completion Waiting Turnaround
1 3 1 4 0 1
2 1 4 6 1 5
3 4 2 8 2 4
4 0 6 16 10 16
5 2 3 11 6 9
Average waiting time: 3.8
Average turnaround time: 7.0