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 class
namedProcess
that hasid
,arrivalTime
, andburstTime
as properties. Theid
is an integer that identifies the process,arrivalTime
is the time at which the process arrives in the ready queue, andburstTime
is the amount of CPU time required by the process. - In the
main
function, create a list ofProcess
objects with differentid
,arrivalTime
, andburstTime
values. - Define the
sjf
function that takes a list ofProcess
objects as input. - Get the number of processes from the input list.
- Create a mutable list
burst
that contains the burst times of all processes. - Create an integer array
remainingTime
that initially contains the burst time of each process. - Create three integer arrays
completionTime
,waitingTime
, andturnaroundTime
to store the completion time, waiting time, and turnaround time of each process. - Initialize the variables
time
,minBurst
,shortest
,check
, andfinished
to 0,Int.MAX_VALUE
, -1,false
, and 0 respectively. - Enter a
while
loop that continues until all processes have been executed. - Inside the loop, use a
for
loop 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
minBurst
andshortest
variables to track the process with the shortest remaining burst time. - Set the
check
variable totrue
if a process has been found. - If no process has been found, increment the
time
variable 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
finished
variable to track the number of completed processes. - Set the
completionTime
of the current process totime + 1
. - Calculate the
turnaroundTime
of the current process by subtracting itsarrivalTime
from itscompletionTime
. - Calculate the
waitingTime
of the current process by subtracting itsburstTime
from itsturnaroundTime
. - If the
waitingTime
of the current process is negative, set it to 0. - Update the
minBurst
variable to find the next process with the shortest remaining burst time. - Increment the
time
variable 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