Skip to content

Add MLFQScheduler.java new algorithm #5575

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 6, 2024
6 changes: 6 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
* [AES](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/AES.java)
* [AESEncryption](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/AESEncryption.java)
* [AffineCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/AffineCipher.java)
* [Autokey](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Autokey.java)
* [Blowfish](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Blowfish.java)
* [Caesar](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/Caesar.java)
* [ColumnarTranspositionCipher](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/ciphers/ColumnarTranspositionCipher.java)
Expand Down Expand Up @@ -203,6 +204,7 @@
* [SameTreesCheck](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/trees/SameTreesCheck.java)
* [SegmentTree](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/trees/SegmentTree.java)
* [SplayTree](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/trees/SplayTree.java)
* [Treap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/trees/Treap.java)
* [TreeRandomNode](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/trees/TreeRandomNode.java)
* [TrieImp](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/trees/TrieImp.java)
* [VerticalOrderTraversal](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversal.java)
Expand Down Expand Up @@ -457,6 +459,7 @@
* [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java)
* scheduling
* [FCFSScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/FCFSScheduling.java)
* [MLFQScheduler](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/MLFQScheduler.java)
* [PreemptivePriorityScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java)
* [RRScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/RRScheduling.java)
* [SJFScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/SJFScheduling.java)
Expand Down Expand Up @@ -618,6 +621,7 @@
* ciphers
* a5
* [LFSRTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/LFSRTest.java)
* [AutokeyTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/AutokeyTest.java)
* [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)
* [CaesarTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/CaesarTest.java)
* [DESTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/DESTest.java)
Expand Down Expand Up @@ -728,6 +732,7 @@
* [PreOrderTraversalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/PreOrderTraversalTest.java)
* [SameTreesCheckTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/SameTreesCheckTest.java)
* [SplayTreeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/SplayTreeTest.java)
* [TreapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/TreapTest.java)
* [TreeTestUtils](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/TreeTestUtils.java)
* [TrieImpTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/TrieImpTest.java)
* [VerticalOrderTraversalTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/trees/VerticalOrderTraversalTest.java)
Expand Down Expand Up @@ -911,6 +916,7 @@
* [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/Recursion/GenerateSubsetsTest.java)
* scheduling
* [FCFSSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/FCFSSchedulingTest.java)
* [MLFQSchedulerTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/MLFQSchedulerTest.java)
* [PreemptivePrioritySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java)
* [RRSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/RRSchedulingTest.java)
* [SJFSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/SJFSchedulingTest.java)
Expand Down
148 changes: 148 additions & 0 deletions src/main/java/com/thealgorithms/scheduling/MLFQScheduler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package com.thealgorithms.scheduling;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
* The Multi-Level Feedback Queue (MLFQ) Scheduler class.
* This class simulates scheduling using multiple queues, where processes move
* between queues depending on their CPU burst behavior.
*/
public class MLFQScheduler {
private List<Queue<Process>> queues; // Multi-level feedback queues
private int[] timeQuantum; // Time quantum for each queue level
private int currentTime; // Current time in the system

/**
* Constructor to initialize the MLFQ scheduler with the specified number of
* levels and their corresponding time quantums.
*
* @param levels Number of queues (priority levels)
* @param timeQuantums Time quantum for each queue level
*/
public MLFQScheduler(int levels, int[] timeQuantums) {
queues = new ArrayList<>(levels);
for (int i = 0; i < levels; i++) {
queues.add(new LinkedList<>());
}
timeQuantum = timeQuantums;
currentTime = 0;
}

/**
* Adds a new process to the highest priority queue (queue 0).
*
* @param p The process to be added to the scheduler
*/
public void addProcess(Process p) {
queues.get(0).add(p);
}

/**
* Executes the scheduling process by running the processes in all queues,
* promoting or demoting them based on their completion status and behavior.
* The process continues until all queues are empty.
*/
public void run() {
while (!allQueuesEmpty()) {
for (int i = 0; i < queues.size(); i++) {
Queue<Process> queue = queues.get(i);
if (!queue.isEmpty()) {
Process p = queue.poll();
int quantum = timeQuantum[i];

// Execute the process for the minimum of the time quantum or the remaining time
int timeSlice = Math.min(quantum, p.remainingTime);
p.execute(timeSlice);
currentTime += timeSlice; // Update the system's current time

if (p.isFinished()) {
System.out.println("Process " + p.pid + " finished at time " + currentTime);
} else {
if (i < queues.size() - 1) {
p.priority++; // Demote the process to the next lower priority queue
queues.get(i + 1).add(p); // Add to the next queue level
} else {
queue.add(p); // Stay in the same queue if it's the last level
}
}
}
}
}
}

/**
* Helper function to check if all the queues are empty (i.e., no process is
* left to execute).
*
* @return true if all queues are empty, otherwise false
*/
private boolean allQueuesEmpty() {
for (Queue<Process> queue : queues) {
if (!queue.isEmpty()) {
return false;
}
}
return true;
}

/**
* Retrieves the current time of the scheduler, which reflects the total time
* elapsed during the execution of all processes.
*
* @return The current time in the system
*/
public int getCurrentTime() {
return currentTime;
}
}

/**
* Represents a process in the Multi-Level Feedback Queue (MLFQ) scheduling
* algorithm.
*/
class Process {
int pid;
int burstTime;
int remainingTime;
int arrivalTime;
int priority;

/**
* Constructor to initialize a new process.
*
* @param pid Process ID
* @param burstTime CPU Burst Time (time required for the process)
* @param arrivalTime Arrival time of the process
*/
Process(int pid, int burstTime, int arrivalTime) {
this.pid = pid;
this.burstTime = burstTime;
this.remainingTime = burstTime;
this.arrivalTime = arrivalTime;
this.priority = 0;
}

/**
* Executes the process for a given time slice.
*
* @param timeSlice The amount of time the process is executed
*/
public void execute(int timeSlice) {
remainingTime -= timeSlice;
if (remainingTime < 0) {
remainingTime = 0;
}
}

/**
* Checks if the process has finished execution.
*
* @return true if the process is finished, otherwise false
*/
public boolean isFinished() {
return remainingTime == 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.thealgorithms.scheduling;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

public class MLFQSchedulerTest {

@Test
void testMLFQScheduling() {
// Create MLFQ Scheduler with 3 levels and time quantum for each level
int[] timeQuantums = {4, 8, 12}; // Example of different quantum for each queue
MLFQScheduler scheduler = new MLFQScheduler(3, timeQuantums);

// Add processes to the scheduler
scheduler.addProcess(new Process(1, 10, 0)); // pid=1, burstTime=10, arrivalTime=0
scheduler.addProcess(new Process(2, 15, 0)); // pid=2, burstTime=15, arrivalTime=0
scheduler.addProcess(new Process(3, 25, 0)); // pid=3, burstTime=25, arrivalTime=0

// Run the scheduler
scheduler.run();

// Check current time after all processes are finished
assertEquals(50, scheduler.getCurrentTime());
}

@Test
void testProcessCompletionOrder() {
int[] timeQuantums = {3, 6, 9};
MLFQScheduler scheduler = new MLFQScheduler(3, timeQuantums);

Process p1 = new Process(1, 10, 0);
Process p2 = new Process(2, 5, 0);
Process p3 = new Process(3, 20, 0);

scheduler.addProcess(p1);
scheduler.addProcess(p2);
scheduler.addProcess(p3);

scheduler.run();

// After running, current time should match the total burst time for all
// processes
assertEquals(35, scheduler.getCurrentTime());
}
}