Task Scheduler
import java.util.LinkedList;
import java.util.Queue;
public class TaskSchedulerByLanguageInstrinsics {
private int maxNumRunningTasks;
private int maxNumPendingTasks;
private Queue<Runnable> pendingTasks = new LinkedList<>();
public TaskSchedulerByLanguageInstrinsics(int maxRunning, int maxPending) {
maxNumRunningTasks = maxRunning;
maxNumPendingTasks = maxPending;
}
public synchronized boolean addTask(Runnable task) {
if (pendingTasks.size() < maxNumPendingTasks) {
pendingTasks.add(task);
notify();
return true;
} else {
return false;
}
}
public synchronized void startTasks() {
for (int i = 0; i < maxNumRunningTasks; ++i) {
new Worker().start();
}
}
private synchronized Runnable getNextTask() {
if (pendingTasks.size() > 0) {
return pendingTasks.remove();
} else {
return null;
}
}
private synchronized void waitForNewTask() throws InterruptedException {
wait();
}
private class Worker extends Thread {
@Override
public void run() {
try {
while(true) {
Runnable task = getNextTask();
if (task != null) {
task.run();
} else {
waitForNewTask();
}
}
} catch (InterruptedException ex) {
System.err.println("Workers should not be interrupted.");
System.exit(1);
}
}
}
// ******************Code below is the test driver, not part of the scheduler implementation.*************
public static void main(String[] args) throws Throwable {
TaskSchedulerByLanguageInstrinsics scheduler = new TaskSchedulerByLanguageInstrinsics(3, 5);
boolean ret = true;
Task initialTask = null;
do {
initialTask = getRandomTask();
ret = scheduler.addTask(initialTask);
if (ret) {
System.out.println("Task " + initialTask.getTaskId() + " added to scheduler.");
} else {
System.out.println("Task " + initialTask.getTaskId() + " rejected by scheduler.");
}
} while (ret);
System.out.println("Starting task scheduler.");
scheduler.startTasks();
Task newTask = initialTask;
while (true) {
// TODO: Change the frequency at which we add new jobs to see how the scheduler behaves.
// E.g. 1000, 3000, 10000
Thread.sleep(3000);
System.out.println("Scheduling task " + newTask.getTaskId());
ret = scheduler.addTask(newTask);
if (ret) {
System.out.println("Task " + newTask.getTaskId() + " added to scheduler.");
newTask = getRandomTask();
} else {
System.out.println("Task " + newTask.getTaskId() + " rejected by scheduler.");
}
}
}
/**
* Returns a task that takes a random amount of time between 3 and 8 seconds.
*/
private static Task getRandomTask() {
final double minTaskTime = 3000;
final double taskTimeRange = 5000;
return new Task((int) (minTaskTime + Math.random() * taskTimeRange));
}
private static class Task implements Runnable {
private static int idCounter = 0;
private int id;
private int timeToCompleteMillis;
public Task(int timeToCompleteMillis) {
id = idCounter++;
this.timeToCompleteMillis = timeToCompleteMillis;
}
public int getTaskId() {
return id;
}
@Override
public void run() {
try {
System.out.println("Performing task " + id + "...");
Thread.sleep(timeToCompleteMillis);
System.out.println("Task " + id + " completed. Time: " + timeToCompleteMillis + " millis.");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}