diff --git a/Client.java b/Client.java index 56b837a..4caf127 100644 --- a/Client.java +++ b/Client.java @@ -26,11 +26,17 @@ public static void main(String[] args) { Job job5 = jobBuilder.name("J5").duration(10).priority(2).deadline(30).user(User.USER).build(); List tasks = List.of(job1, job2, job3, job4, job5); + JobScheduler sjfScheduler = new JobScheduler(new SjfStrategy(), threadManager); + sjfScheduler.scheduleJobs(tasks); - System.out.println("SJF"); - threadManager.schedule(new SjfStrategy(), tasks); + threadManager.init(2); + JobScheduler fcfsScheduler = new JobScheduler(new FcfsStrategy(), threadManager); + fcfsScheduler.scheduleJobs(tasks); + +// System.out.println("SJF"); +// threadManager.schedule(new SjfStrategy(), tasks); - System.out.println("FCFS"); - threadManager.schedule(new FcfsStrategy(), tasks); +// System.out.println("FCFS"); +// threadManager.schedule(new FcfsStrategy(), tasks); } } diff --git a/Entities/Worker.java b/Entities/Worker.java index 9f1a914..9757031 100644 --- a/Entities/Worker.java +++ b/Entities/Worker.java @@ -6,9 +6,9 @@ // Workers are threads that will execute the jobs in this system public class Worker { //jobs that will be assigned to this thread - List jobs; - int availableAt; - int id; + private List jobs; + private Integer availableAt; + private Integer id; public int getId() { return id; } public int getAvailableAt() { @@ -18,6 +18,11 @@ public void setAvailableAt(int availableAt) { this.availableAt = availableAt; } + public List getJobs(){ + return jobs; + } + + private Worker(){} // making a private constructor so that no one can make a worker with empty id public Worker(int id) { jobs = new ArrayList<>(); availableAt = 0; diff --git a/JobScheduler.java b/JobScheduler.java new file mode 100644 index 0000000..1546a6f --- /dev/null +++ b/JobScheduler.java @@ -0,0 +1,18 @@ +import Entities.Job; +import SchedulingStrategy.ISchedulingStrategy; +import Threads.ThreadManager; + +import java.util.List; + +public class JobScheduler { + private final ISchedulingStrategy strategy; + private final ThreadManager threadManager; + JobScheduler(ISchedulingStrategy strategy, ThreadManager threadManager){ + this.strategy = strategy; + this.threadManager = threadManager; + } + public void scheduleJobs(List jobs){ + strategy.run(threadManager,jobs); + threadManager.print(); + } +} diff --git a/SchedulingStrategy/FcfsStrategy.java b/SchedulingStrategy/FcfsStrategy.java index 46fbfaa..2526795 100644 --- a/SchedulingStrategy/FcfsStrategy.java +++ b/SchedulingStrategy/FcfsStrategy.java @@ -2,15 +2,20 @@ import Entities.Job; import Entities.Worker; +import Threads.ThreadManager; +import java.util.ArrayList; +import java.util.Comparator; import java.util.List; import java.util.PriorityQueue; public class FcfsStrategy implements ISchedulingStrategy { @Override - public void run(PriorityQueue workers, List jobs){ + public void run(ThreadManager threadManager, List jobs){ // no need to sort the jobs assuming arrival time is 0 for all of them - readJobs(workers, jobs); + for(var j : jobs){ + threadManager.assignJobToWorkerThread(j); + } } } diff --git a/SchedulingStrategy/ISchedulingStrategy.java b/SchedulingStrategy/ISchedulingStrategy.java index 8ad1b47..1ec770e 100644 --- a/SchedulingStrategy/ISchedulingStrategy.java +++ b/SchedulingStrategy/ISchedulingStrategy.java @@ -2,6 +2,7 @@ import Entities.Job; import Entities.Worker; +import Threads.ThreadManager; import java.util.ArrayList; import java.util.Comparator; @@ -10,7 +11,7 @@ public interface ISchedulingStrategy { - void run(PriorityQueue workers, List jobs); + void run(ThreadManager threadManager, List jobs); default void readJobs(PriorityQueue workers, List jobs) { for(var job : jobs) { Worker current = workers.poll(); diff --git a/SchedulingStrategy/SjfStrategy.java b/SchedulingStrategy/SjfStrategy.java index df96bc1..43b054a 100644 --- a/SchedulingStrategy/SjfStrategy.java +++ b/SchedulingStrategy/SjfStrategy.java @@ -2,6 +2,7 @@ import Entities.Job; import Entities.Worker; +import Threads.ThreadManager; import java.util.ArrayList; import java.util.Comparator; @@ -9,10 +10,20 @@ import java.util.PriorityQueue; public class SjfStrategy implements ISchedulingStrategy { + + /** + * Shortest Job first - SJF + * Shortest job first (SJF), is a scheduling policy that selects the waiting process with the smallest execution time to execute next. + * In case of tie choose the job according to the following order - + * 1. Priority (higher priority job gets scheduled first) + */ + @Override - public void run(PriorityQueue workers, List tasks) { + public void run(ThreadManager threadManager, List tasks) { List jobs = new ArrayList<>(tasks); - jobs.sort(Comparator.comparingInt(Job::getDuration)); - readJobs(workers, jobs); + jobs.sort(Comparator.comparingInt(Job::getDuration).thenComparing(Job::getPriority)); + for(var j : jobs){ + threadManager.assignJobToWorkerThread(j); + } } } diff --git a/Threads/ThreadManager.java b/Threads/ThreadManager.java index bac0a3b..7634adf 100644 --- a/Threads/ThreadManager.java +++ b/Threads/ThreadManager.java @@ -4,17 +4,26 @@ import Entities.Worker; import SchedulingStrategy.ISchedulingStrategy; +import java.util.ArrayList; import java.util.Comparator; import java.util.PriorityQueue; import java.util.List; // Holds instance of threads and abstracts it from client +// Responsibility : + +/** + * Manage Thread LifeCycle : Creation, Job Assignment and Storage of Thread Workers + */ public class ThreadManager { private static ThreadManager INSTANCE = null; - PriorityQueue pq; + private PriorityQueue pq; - public ThreadManager() { - pq = new PriorityQueue<>(Comparator.comparingInt(Worker::getAvailableAt)); + private ThreadManager() { // this should be private if you want to make it singleton. + pq = new PriorityQueue<>(Comparator.comparingInt(Worker::getAvailableAt) + .thenComparing(Worker::getId) + ); + // so if 2 threads are getting available at same time, i should choose the one which has smaller id. } public static ThreadManager getInstance() { @@ -24,6 +33,19 @@ public static ThreadManager getInstance() { return INSTANCE; } + public void assignJobToWorkerThread(Job j){ + // polling the worker with the earliest available time. + if(pq.isEmpty()) throw new RuntimeException("No workers available"); + var worker = pq.poll(); + if(worker.getAvailableAt() <= j.getDeadline()){ + worker.setAvailableAt(worker.getAvailableAt() + j.duration); + worker.addJob(j); // assigning the job + pq.add(worker); // adding the worker to the pool + }else { + pq.add(worker); + } + } + public void init(int numOfWorkers) { if(numOfWorkers <= 0) return; @@ -35,8 +57,20 @@ public void init(int numOfWorkers) { } } - public void schedule(ISchedulingStrategy strategy, List jobs) { - strategy.run(pq, jobs); - init(pq.size()); + public void reset(){ + if(pq != null && !pq.isEmpty()) + this.init(pq.size()); } + + public void print(){ + List workers = new ArrayList<>(); + while(!pq.isEmpty()){ + workers.add(pq.poll()); + } + workers.sort(Comparator.comparing(Worker::getId)); + for(var w : workers){ + System.out.println("Thread " + w.getId() + " : " + w.getJobs().toString()); + } + } + } diff --git a/lld.png b/lld.png new file mode 100644 index 0000000..e1760f2 Binary files /dev/null and b/lld.png differ