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