diff --git a/DIRECTORY.md b/DIRECTORY.md index 774a18601..476308a35 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -523,6 +523,7 @@ * Recursion * [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java) * scheduling + * [AgingScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/AgingScheduling.java) * diskscheduling * [CircularLookScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularLookScheduling.java) * [CircularScanScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/diskscheduling/CircularScanScheduling.java) @@ -1123,6 +1124,7 @@ * Recursion * [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/Recursion/GenerateSubsetsTest.java) * scheduling + * [AgingSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/AgingSchedulingTest.java) * diskscheduling * [CircularLookSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularLookSchedulingTest.java) * [CircularScanSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/diskscheduling/CircularScanSchedulingTest.java) diff --git a/src/main/java/com/thealgorithms/scheduling/AgingScheduling.java b/src/main/java/com/thealgorithms/scheduling/AgingScheduling.java new file mode 100644 index 000000000..1e5512be9 --- /dev/null +++ b/src/main/java/com/thealgorithms/scheduling/AgingScheduling.java @@ -0,0 +1,62 @@ +package com.thealgorithms.scheduling; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * AgingScheduling is an algorithm designed to prevent starvation + * by gradually increasing the priority of waiting tasks. + * The longer a process waits, the higher its priority becomes. + * + * Use Case: Useful in systems with mixed workloads to avoid + * lower-priority tasks being starved by higher-priority tasks. + * + * @author Hardvan + */ +public final class AgingScheduling { + + static class Task { + String name; + int waitTime; + int priority; + + Task(String name, int priority) { + this.name = name; + this.priority = priority; + this.waitTime = 0; + } + } + + private final Queue taskQueue; + + public AgingScheduling() { + taskQueue = new LinkedList<>(); + } + + /** + * Adds a task to the scheduler with a given priority. + * + * @param name name of the task + * @param priority priority of the task + */ + public void addTask(String name, int priority) { + taskQueue.offer(new Task(name, priority)); + } + + /** + * Schedules the next task based on the priority and wait time. + * The priority of a task increases with the time it spends waiting. + * + * @return name of the next task to be executed + */ + public String scheduleNext() { + if (taskQueue.isEmpty()) { + return null; + } + Task nextTask = taskQueue.poll(); + nextTask.waitTime++; + nextTask.priority += nextTask.waitTime; + taskQueue.offer(nextTask); + return nextTask.name; + } +} diff --git a/src/test/java/com/thealgorithms/scheduling/AgingSchedulingTest.java b/src/test/java/com/thealgorithms/scheduling/AgingSchedulingTest.java new file mode 100644 index 000000000..cab78e4d1 --- /dev/null +++ b/src/test/java/com/thealgorithms/scheduling/AgingSchedulingTest.java @@ -0,0 +1,54 @@ +package com.thealgorithms.scheduling; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class AgingSchedulingTest { + + private AgingScheduling scheduler; + + @BeforeEach + public void setup() { + scheduler = new AgingScheduling(); + } + + @Test + public void testAddAndScheduleSingleTask() { + scheduler.addTask("Task1", 5); + assertEquals("Task1", scheduler.scheduleNext()); + } + + @Test + public void testAddMultipleTasks() { + scheduler.addTask("Task1", 1); + scheduler.addTask("Task2", 1); + assertEquals("Task1", scheduler.scheduleNext()); + assertEquals("Task2", scheduler.scheduleNext()); + } + + @Test + public void testPriorityAdjustmentWithWait() { + scheduler.addTask("Task1", 1); + scheduler.addTask("Task2", 1); + scheduler.scheduleNext(); + scheduler.scheduleNext(); + assertEquals("Task1", scheduler.scheduleNext()); + } + + @Test + public void testEmptyScheduler() { + assertNull(scheduler.scheduleNext()); + } + + @Test + public void testMultipleRounds() { + scheduler.addTask("Task1", 1); + scheduler.addTask("Task2", 2); + scheduler.scheduleNext(); + scheduler.scheduleNext(); + assertEquals("Task1", scheduler.scheduleNext()); + } +}