Skip to content

Instantly share code, notes, and snippets.

@sourcedelica
Created March 12, 2016 14:41
Show Gist options
  • Save sourcedelica/adf75682e937e20daa50 to your computer and use it in GitHub Desktop.
Save sourcedelica/adf75682e937e20daa50 to your computer and use it in GitHub Desktop.
/**
* EPI 20.6
* O(n) space
* Start: O(log n)
* Cancel: O(n)
* Cancel could be improved to O(log n) using IndexedMinPQ instead of DelayQueue.
* You would also need to manage the poller thread wakeups
* and would need to synchronize on the queue.
*/
public class Timer {
ConcurrentHashMap<String, Task> map = new ConcurrentHashMap<>();
DelayQueue<Task> delayQueue = new DelayQueue<>();
final Thread poller;
public Timer() {
poller = new Thread() {
public void run() {
boolean run = true;
while (run) {
try {
Task task = delayQueue.take();
Thread t = new Thread(task.runnable);
t.start();
} catch (InterruptedException ex) {
run = false;
}
}
}
};
poller.start();
}
static class Task implements Delayed {
long start;
Runnable runnable;
Task(long start, Runnable runnable) { this.start = start; this.runnable = runnable; }
public long getDelay(TimeUnit unit) { return start - System.currentTimeMillis(); }
public int compareTo(Delayed that) { return Long.compare(start, ((Task)that).start); }
}
public void start(String name, long delayMs, Runnable runnable) {
if (map.containsKey(name)) throw new IllegalArgumentException("Name already exists: " + name);
Task task = new Task(System.currentTimeMillis() + delayMs, runnable);
map.put(name, task);
delayQueue.add(task);
}
public void cancel(String name) {
Task task = map.remove(name);
if (task == null) throw new IllegalArgumentException("Task does not exist: " + name);
delayQueue.remove(task);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment