mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-23 20:44:39 +08:00
Add LotteryScheduling
algorithm (#5656)
This commit is contained in:
@ -0,0 +1,141 @@
|
||||
package com.thealgorithms.scheduling;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* The LotteryScheduling class implements the Lottery Scheduling algorithm, which is
|
||||
* a probabilistic CPU scheduling algorithm. Processes are assigned tickets, and
|
||||
* the CPU is allocated to a randomly selected process based on ticket count.
|
||||
* Processes with more tickets have a higher chance of being selected.
|
||||
*/
|
||||
public final class LotteryScheduling {
|
||||
private LotteryScheduling() {
|
||||
}
|
||||
|
||||
private List<Process> processes;
|
||||
private Random random;
|
||||
|
||||
/**
|
||||
* Constructs a LotteryScheduling object with the provided list of processes.
|
||||
*
|
||||
* @param processes List of processes to be scheduled using Lottery Scheduling.
|
||||
*/
|
||||
public LotteryScheduling(final List<Process> processes) {
|
||||
this.processes = processes;
|
||||
this.random = new Random();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a LotteryScheduling object with the provided list of processes and a Random object.
|
||||
*
|
||||
* @param processes List of processes to be scheduled using Lottery Scheduling.
|
||||
* @param random Random object used for generating random numbers.
|
||||
*/
|
||||
public LotteryScheduling(final List<Process> processes, Random random) {
|
||||
this.processes = processes;
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the processes using the Lottery Scheduling algorithm.
|
||||
* Each process is assigned a certain number of tickets, and the algorithm randomly
|
||||
* selects a process to execute based on ticket count. The method calculates the
|
||||
* waiting time and turnaround time for each process and simulates their execution.
|
||||
*/
|
||||
public List<Process> scheduleProcesses() {
|
||||
int totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
|
||||
int currentTime = 0;
|
||||
List<Process> executedProcesses = new ArrayList<>();
|
||||
|
||||
while (!processes.isEmpty()) {
|
||||
int winningTicket = random.nextInt(totalTickets) + 1;
|
||||
Process selectedProcess = selectProcessByTicket(winningTicket);
|
||||
|
||||
if (selectedProcess == null) {
|
||||
// This should not happen in normal circumstances, but we'll handle it just in case
|
||||
System.err.println("Error: No process selected. Recalculating total tickets.");
|
||||
totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
|
||||
continue;
|
||||
}
|
||||
|
||||
selectedProcess.setWaitingTime(currentTime);
|
||||
currentTime += selectedProcess.getBurstTime();
|
||||
selectedProcess.setTurnAroundTime(selectedProcess.getWaitingTime() + selectedProcess.getBurstTime());
|
||||
|
||||
executedProcesses.add(selectedProcess);
|
||||
processes.remove(selectedProcess);
|
||||
|
||||
totalTickets = processes.stream().mapToInt(Process::getTickets).sum();
|
||||
}
|
||||
|
||||
return executedProcesses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a process based on a winning ticket. The method iterates over the
|
||||
* list of processes, and as the ticket sum accumulates, it checks if the
|
||||
* current process holds the winning ticket.
|
||||
*
|
||||
* @param winningTicket The randomly generated ticket number that determines the selected process.
|
||||
* @return The process associated with the winning ticket.
|
||||
*/
|
||||
private Process selectProcessByTicket(int winningTicket) {
|
||||
int ticketSum = 0;
|
||||
for (Process process : processes) {
|
||||
ticketSum += process.getTickets();
|
||||
if (ticketSum >= winningTicket) {
|
||||
return process;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Process class represents a process in the scheduling system. Each process has
|
||||
* an ID, burst time (CPU time required for execution), number of tickets (used in
|
||||
* lottery selection), waiting time, and turnaround time.
|
||||
*/
|
||||
public static class Process {
|
||||
private String processId;
|
||||
private int burstTime;
|
||||
private int tickets;
|
||||
private int waitingTime;
|
||||
private int turnAroundTime;
|
||||
|
||||
public Process(String processId, int burstTime, int tickets) {
|
||||
this.processId = processId;
|
||||
this.burstTime = burstTime;
|
||||
this.tickets = tickets;
|
||||
}
|
||||
|
||||
public String getProcessId() {
|
||||
return processId;
|
||||
}
|
||||
|
||||
public int getBurstTime() {
|
||||
return burstTime;
|
||||
}
|
||||
|
||||
public int getTickets() {
|
||||
return tickets;
|
||||
}
|
||||
|
||||
public int getWaitingTime() {
|
||||
return waitingTime;
|
||||
}
|
||||
|
||||
public void setWaitingTime(int waitingTime) {
|
||||
this.waitingTime = waitingTime;
|
||||
}
|
||||
|
||||
public int getTurnAroundTime() {
|
||||
return turnAroundTime;
|
||||
}
|
||||
|
||||
public void setTurnAroundTime(int turnAroundTime) {
|
||||
this.turnAroundTime = turnAroundTime;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.thealgorithms.scheduling;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class LotterySchedulingTest {
|
||||
|
||||
private Random mockRandom;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
mockRandom = mock(Random.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLotterySchedulingWithMockedRandom() {
|
||||
List<LotteryScheduling.Process> processes = createProcesses();
|
||||
LotteryScheduling lotteryScheduling = new LotteryScheduling(processes, mockRandom);
|
||||
|
||||
// Mock the sequence of random numbers (winning tickets)
|
||||
// This sequence ensures that P1 (10 tickets), P3 (8 tickets), and P2 (5 tickets) are selected.
|
||||
when(mockRandom.nextInt(23)).thenReturn(5, 18, 11); // winning tickets for P1, P3, and P2
|
||||
|
||||
List<LotteryScheduling.Process> executedProcesses = lotteryScheduling.scheduleProcesses();
|
||||
|
||||
assertEquals(3, executedProcesses.size());
|
||||
|
||||
// Assert the process execution order and properties
|
||||
LotteryScheduling.Process process1 = executedProcesses.get(0);
|
||||
assertEquals("P1", process1.getProcessId());
|
||||
assertEquals(0, process1.getWaitingTime());
|
||||
assertEquals(10, process1.getTurnAroundTime());
|
||||
|
||||
LotteryScheduling.Process process2 = executedProcesses.get(1);
|
||||
assertEquals("P2", process2.getProcessId());
|
||||
assertEquals(10, process2.getWaitingTime());
|
||||
assertEquals(15, process2.getTurnAroundTime());
|
||||
|
||||
LotteryScheduling.Process process3 = executedProcesses.get(2);
|
||||
assertEquals("P3", process3.getProcessId());
|
||||
assertEquals(15, process3.getWaitingTime());
|
||||
assertEquals(23, process3.getTurnAroundTime());
|
||||
}
|
||||
|
||||
private List<LotteryScheduling.Process> createProcesses() {
|
||||
LotteryScheduling.Process process1 = new LotteryScheduling.Process("P1", 10, 10); // 10 tickets
|
||||
LotteryScheduling.Process process2 = new LotteryScheduling.Process("P2", 5, 5); // 5 tickets
|
||||
LotteryScheduling.Process process3 = new LotteryScheduling.Process("P3", 8, 8); // 8 tickets
|
||||
|
||||
List<LotteryScheduling.Process> processes = new ArrayList<>();
|
||||
processes.add(process1);
|
||||
processes.add(process2);
|
||||
processes.add(process3);
|
||||
|
||||
return processes;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user