
Hey folks, recently I appeared for a couple of companies focusing on Mutli-threading and concurrency theory.
You can directly jump to the code part, if you have the famous paid subscription course.
And here is the complete code: Multi-Threaded-Task-Scheduler.
P.S. After watching the videos mentioned below, you should be able to completely understand my code, hence skipping the explanation part.
The only coding pattern I could think of using was Singleton pattern and factory pattern.
public class SchedulerService implements ISchedulerService {
private static ISchedulerService schedulerService;
private final PriorityQueue<ScheduledTask> taskPriorityQueue;
private final ThreadPoolExecutor taskExecutor;
private final Lock lock;
private final Condition newTaskScheduled;
private SchedulerService(int thread_size) {
this.taskPriorityQueue = new PriorityQueue<>(Comparator.comparingLong(ScheduledTask::getScheduledTime));
this.taskExecutor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
this.lock = new ReentrantLock();
this.newTaskScheduled = this.lock.newCondition();
}
@Override
public void run() {
Long time_to_sleep = Long.valueOf(0);
while (true) {
this.lock.lock();
try {
while (this.taskPriorityQueue.isEmpty()) {this.newTaskScheduled.await();}
while(!this.taskPriorityQueue.isEmpty()) {
time_to_sleep = this.taskPriorityQueue.peek().getTimeUnit().toMillis(this.taskPriorityQueue.peek().getScheduledTime()) - System.currentTimeMillis();
if (time_to_sleep <= 0) break;
this.newTaskScheduled.await(time_to_sleep, TimeUnit.MILLISECONDS);
}
ScheduledTask scheduledTask = this.taskPriorityQueue.poll();
Long newScheduledTime = Long.valueOf(0);
switch (scheduledTask.getScheduledTaskType()) {
case RUN_ONCE -> {
this.taskExecutor.submit(scheduledTask.getTask());
break;
}
case RECUR -> {
newScheduledTime = System.currentTimeMillis()+ scheduledTask.getTimeUnit().toMillis(scheduledTask.getReplayTime());
this.taskExecutor.submit(scheduledTask.getTask());
scheduledTask.setScheduledTime(newScheduledTime);
this.taskPriorityQueue.add(scheduledTask);
break;
}
case RECUR_WITH_WAIT -> {
Future<?> future = this.taskExecutor.submit(scheduledTask.getTask());
future.get();
newScheduledTime = System.currentTimeMillis()+ scheduledTask.getTimeUnit().toMillis(scheduledTask.getReplayTime());
scheduledTask.setScheduledTime(newScheduledTime);
this.taskPriorityQueue.add(scheduledTask);
break;
}
}
} catch (RejectedExecutionException r) {
r.printStackTrace();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
} finally {
this.lock.unlock();
}
}
}
}Videos explaining some of the standard multithreaded coding examples