From 44c05bf7db34c9e0458b82b82bf7b0aa69421af7 Mon Sep 17 00:00:00 2001
From: thanoskiver <83243257+thanoskiver@users.noreply.github.com>
Date: Fri, 13 Jan 2023 21:22:45 +0200
Subject: [PATCH] Add Shortest Job First Scheduling (#3843)
---
.../java/com/thealgorithms/others/SJF.java | 199 ------------------
.../scheduling/SJFScheduling.java | 115 ++++++++++
.../scheduling/SJFSchedulingTest.java | 120 +++++++++++
3 files changed, 235 insertions(+), 199 deletions(-)
delete mode 100644 src/main/java/com/thealgorithms/others/SJF.java
create mode 100644 src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
create mode 100644 src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java
diff --git a/src/main/java/com/thealgorithms/others/SJF.java b/src/main/java/com/thealgorithms/others/SJF.java
deleted file mode 100644
index 17147412..00000000
--- a/src/main/java/com/thealgorithms/others/SJF.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package com.thealgorithms.others;
-
-/**
- *
- *
- *
Shortest job first.
- *
- *
- * Shortest job first (SJF) or shortest job next, is a scheduling policy that
- * selects the waiting process with the smallest execution time to execute next
- * Shortest Job first has the advantage of having minimum average waiting time
- * among all scheduling algorithms. It is a Greedy Algorithm. It may cause
- * starvation if shorter processes keep coming. This problem has been solved
- * using the concept of aging.
- *
- * @author shivg7706
- * @since 2018/10/27
- */
-import java.util.*;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Scanner;
-
-class Process {
-
- public int pid;
- public int arrivalTime;
- public int burstTime;
- public int priority;
- public int turnAroundTime;
- public int waitTime;
- public int remainingTime;
-}
-
-class Schedule {
-
- private int noOfProcess;
- private int timer = 0;
- private ArrayList processes;
- private ArrayList remainingProcess;
- private ArrayList gantChart;
- private float burstAll;
- private Map> arrivals;
-
- Schedule() {
- Scanner in = new Scanner(System.in);
-
- processes = new ArrayList();
- remainingProcess = new ArrayList();
-
- gantChart = new ArrayList<>();
- arrivals = new HashMap<>();
-
- System.out.print("Enter the no. of processes: ");
- noOfProcess = in.nextInt();
- System.out.println(
- "Enter the arrival, burst and priority of processes"
- );
- for (int i = 0; i < noOfProcess; i++) {
- Process p = new Process();
- p.pid = i;
- p.arrivalTime = in.nextInt();
- p.burstTime = in.nextInt();
- p.priority = in.nextInt();
- p.turnAroundTime = 0;
- p.waitTime = 0;
- p.remainingTime = p.burstTime;
-
- if (arrivals.get(p.arrivalTime) == null) {
- arrivals.put(p.arrivalTime, new ArrayList());
- }
- arrivals.get(p.arrivalTime).add(p);
- processes.add(p);
- burstAll += p.burstTime;
- }
- in.close();
- }
-
- void startScheduling() {
- processes.sort(
- new Comparator() {
- @Override
- public int compare(Process a, Process b) {
- return a.arrivalTime - b.arrivalTime;
- }
- }
- );
-
- while (!(arrivals.size() == 0 && remainingProcess.size() == 0)) {
- removeFinishedProcess();
- if (arrivals.get(timer) != null) {
- remainingProcess.addAll(arrivals.get(timer));
- arrivals.remove(timer);
- }
-
- remainingProcess.sort(
- new Comparator() {
- private int alpha = 6;
- private int beta = 1;
-
- @Override
- public int compare(Process a, Process b) {
- int aRem = a.remainingTime;
- int bRem = b.remainingTime;
- int aprior = a.priority;
- int bprior = b.priority;
- return (
- (alpha * aRem + beta * aprior) -
- (alpha * bRem + beta * bprior)
- );
- }
- }
- );
-
- int k = timeElapsed(timer);
- ageing(k);
- timer++;
- }
-
- System.out.println("Total time required: " + (timer - 1));
- }
-
- void removeFinishedProcess() {
- ArrayList completed = new ArrayList();
- for (int i = 0; i < remainingProcess.size(); i++) {
- if (remainingProcess.get(i).remainingTime == 0) {
- completed.add(i);
- }
- }
-
- for (int i = 0; i < completed.size(); i++) {
- int pid = remainingProcess.get(completed.get(i)).pid;
- processes.get(pid).waitTime =
- remainingProcess.get(completed.get(i)).waitTime;
- remainingProcess.remove(remainingProcess.get(completed.get(i)));
- }
- }
-
- public int timeElapsed(int i) {
- if (!remainingProcess.isEmpty()) {
- gantChart.add(i, remainingProcess.get(0).pid);
- remainingProcess.get(0).remainingTime--;
- return 1;
- }
- return 0;
- }
-
- public void ageing(int k) {
- for (int i = k; i < remainingProcess.size(); i++) {
- remainingProcess.get(i).waitTime++;
- if (remainingProcess.get(i).waitTime % 7 == 0) {
- remainingProcess.get(i).priority--;
- }
- }
- }
-
- public void solve() {
- System.out.println("Gant chart ");
- for (int i = 0; i < gantChart.size(); i++) {
- System.out.print(gantChart.get(i) + " ");
- }
- System.out.println();
-
- float waitTimeTot = 0;
- float tatTime = 0;
-
- for (int i = 0; i < noOfProcess; i++) {
- processes.get(i).turnAroundTime =
- processes.get(i).waitTime + processes.get(i).burstTime;
-
- waitTimeTot += processes.get(i).waitTime;
- tatTime += processes.get(i).turnAroundTime;
-
- System.out.println(
- "Process no.: " +
- i +
- " Wait time: " +
- processes.get(i).waitTime +
- " Turn Around Time: " +
- processes.get(i).turnAroundTime
- );
- }
-
- System.out.println(
- "Average Waiting Time: " + waitTimeTot / noOfProcess
- );
- System.out.println("Average TAT Time: " + tatTime / noOfProcess);
- System.out.println("Throughput: " + (float) noOfProcess / (timer - 1));
- }
-}
-
-public class SJF {
-
- public static void main(String[] args) {
- Schedule s = new Schedule();
- s.startScheduling();
- s.solve();
- }
-}
diff --git a/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java b/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
new file mode 100644
index 00000000..bf3a9f00
--- /dev/null
+++ b/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java
@@ -0,0 +1,115 @@
+package com.thealgorithms.scheduling;
+
+import com.thealgorithms.devutils.entities.ProcessDetails;
+
+import java.util.ArrayList;
+
+/**
+ * Implementation of Shortest Job First Algorithm: The algorithm allows the waiting process with the minimal burst time to be executed first.
+ * see more here: https://www.guru99.com/shortest-job-first-sjf-scheduling.html
+ */
+
+public class SJFScheduling {
+ protected ArrayList processes;
+ protected ArrayListschedule ;
+
+ /**
+ * a simple constructor
+ * @param processes a list of processes the user wants to schedule
+ * it also sorts the processes based on the time of their arrival
+ */
+ SJFScheduling(final ArrayList processes) {
+ this.processes = processes;
+ schedule=new ArrayList<>();
+ sortByArrivalTime();
+ }
+protected void sortByArrivalTime() {
+ int size=processes.size(),i,j;
+ ProcessDetails temp;
+ for(i=0;iprocesses.get(j+1).getArrivalTime())
+ {
+ temp=processes.get(j);
+ processes.set(j,processes.get(j+1));
+ processes.set(j+1,temp);
+ }
+ }
+ }
+
+}
+
+ /**
+ * this functions returns the order of the executions
+ */
+
+ public void scheduleProcesses() {
+ ArrayList ready=new ArrayList<>();
+
+ int size = processes.size(),runtime,time=0;
+ int executed=0,j,k=0;
+ ProcessDetails running;
+
+ if (size == 0) {
+ return;
+ }
+
+
+ while(executed ReadyProcesses) {
+ if (ReadyProcesses.isEmpty()){
+ return null;
+ }
+ int i,size = ReadyProcesses.size();
+ int minBurstTime = ReadyProcesses.get(0).getBurstTime(), temp, positionOfShortestJob = 0;
+
+
+ for (i = 1; i < size; i++) {
+ temp = ReadyProcesses.get(i).getBurstTime();
+ if (minBurstTime > temp ) {
+ minBurstTime = temp;
+ positionOfShortestJob = i;
+ }
+ }
+
+ return ReadyProcesses.get(positionOfShortestJob);
+ }
+
+
+
+
+
+ }
+
diff --git a/src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java
new file mode 100644
index 00000000..8ba3b679
--- /dev/null
+++ b/src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java
@@ -0,0 +1,120 @@
+package com.thealgorithms.scheduling;
+
+import com.thealgorithms.devutils.entities.ProcessDetails;
+import org.junit.jupiter.api.Test;
+
+import java.util.ArrayList;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class SJFSchedulingTest {
+ private ArrayList process;
+ void initialisation0()
+ {
+
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,6));
+ process.add(new ProcessDetails("2",1,2));
+ }
+ void initialisation1()
+ {
+
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,6));
+ process.add(new ProcessDetails("2",1,2));
+ process.add(new ProcessDetails("3",4 ,3));
+ process.add(new ProcessDetails("4",3,1));
+ process.add(new ProcessDetails("5",6 ,4));
+ process.add(new ProcessDetails("6",5,5));
+ }
+
+ void initialisation2()
+ {
+
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,3));
+ process.add(new ProcessDetails("2",1,2));
+ process.add(new ProcessDetails("3",2 ,1));
+
+ }
+ void initialisation3(){
+ process=new ArrayList<>();
+ process.add(new ProcessDetails("1",0 ,3));
+ process.add(new ProcessDetails("2",5,2));
+ process.add(new ProcessDetails("3",9 ,1));
+ }
+ @Test
+ void constructor()
+ {
+ initialisation0();
+ SJFScheduling a=new SJFScheduling(process);
+ assertEquals( 6,a.processes.get(0).getBurstTime());
+ assertEquals( 2,a.processes.get(1).getBurstTime());
+ }
+
+ @Test
+ void sort()
+ {
+ initialisation1();
+ SJFScheduling a=new SJFScheduling(process);
+ a.sortByArrivalTime();
+ assertEquals("1",a.processes.get(0).getProcessId());
+ assertEquals("2",a.processes.get(1).getProcessId());
+ assertEquals("3",a.processes.get(3).getProcessId());
+ assertEquals("4",a.processes.get(2).getProcessId());
+ assertEquals("5",a.processes.get(5).getProcessId());
+ assertEquals("6",a.processes.get(4).getProcessId());
+
+ }
+
+ @Test
+ void scheduling(){
+ initialisation1();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "4" , a.schedule.get(1));
+ assertEquals( "2" , a.schedule.get(2));
+ assertEquals( "3" , a.schedule.get(3));
+ assertEquals("5" , a.schedule.get(4));
+ assertEquals( "6", a.schedule.get(5));
+
+
+ }
+
+ @Test
+ void schedulingOf_TwoProcesses(){
+ initialisation0();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "2" , a.schedule.get(1));
+ }
+
+ @Test
+ void schedulingOfA_ShortestJobArrivingLast(){
+ initialisation2();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "3" , a.schedule.get(1));
+ assertEquals( "2" , a.schedule.get(2));
+ }
+ @Test
+ void scheduling_WithProcessesNotComingBackToBack(){
+ initialisation3();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertEquals( "1" , a.schedule.get(0));
+ assertEquals( "2" , a.schedule.get(1));
+ assertEquals( "3" , a.schedule.get(2));
+ }
+ @Test
+ void schedulingOf_nothing(){
+ process=new ArrayList<>();
+ SJFScheduling a=new SJFScheduling(process);
+ a.scheduleProcesses();
+ assertTrue( a.schedule.isEmpty());
+
+ }
+}
\ No newline at end of file