@Test public void testConcurrentAddDelay() throws InterruptedException { ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); final Object tc = this; SingletonTask st1 = new SingletonTask(ses, new Runnable() { @Override public void run() { synchronized (tc) { ran += 1; } try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (tc) { finished += 1; time = System.nanoTime(); } } }); long start = System.nanoTime(); st1.reschedule(5, TimeUnit.MILLISECONDS); Thread.sleep(20); assertEquals("Check that task started", 1, ran); assertEquals("Check that task not finished", 0, finished); st1.reschedule(75, TimeUnit.MILLISECONDS); assertTrue("Check task running state true", st1.context.taskRunning); assertTrue("Check task should run state true", st1.context.taskShouldRun); assertEquals("Check that task started", 1, ran); assertEquals("Check that task not finished", 0, finished); Thread.sleep(150); assertTrue("Check task running state false", !st1.context.taskRunning); assertTrue("Check task should run state false", !st1.context.taskShouldRun); assertEquals("Check that task ran exactly twice", 2, ran); assertEquals("Check that task finished exactly twice", 2, finished); assertTrue("Check that time passed appropriately: " + (time - start), (time - start) >= TimeUnit.NANOSECONDS.convert(130, TimeUnit.MILLISECONDS)); assertTrue("Check that time passed appropriately: " + (time - start), (time - start) <= TimeUnit.NANOSECONDS.convert(160, TimeUnit.MILLISECONDS)); ses.shutdown(); ses.awaitTermination(5, TimeUnit.SECONDS); }
public void reschedule(long delay, TimeUnit unit) { boolean needQueue = true; SingletonTaskWorker stw = null; synchronized (context) { if (context.taskRunning || context.taskShouldRun) { if (context.taskRunning) { if (delay > 0) { long now = System.nanoTime(); long then = now + TimeUnit.NANOSECONDS.convert(delay, unit); context.waitingTask.nextschedule = then; } else { context.waitingTask.nextschedule = 0; } needQueue = false; } else { context.waitingTask.canceled = true; context.waitingTask = null; } } context.taskShouldRun = true; if (needQueue) { stw = context.waitingTask = new SingletonTaskWorker(this); } } if (needQueue) { if (delay <= 0) ses.execute(stw); else ses.schedule(stw, delay, unit); } }
SingletonTask { public void reschedule(long delay, TimeUnit unit) { boolean needQueue = true; SingletonTaskWorker stw = null; synchronized (context) { if (context.taskRunning || context.taskShouldRun) { if (context.taskRunning) { if (delay > 0) { long now = System.nanoTime(); long then = now + TimeUnit.NANOSECONDS.convert(delay, unit); context.waitingTask.nextschedule = then; } else { context.waitingTask.nextschedule = 0; } needQueue = false; } else { context.waitingTask.canceled = true; context.waitingTask = null; } } context.taskShouldRun = true; if (needQueue) { stw = context.waitingTask = new SingletonTaskWorker(this); } } if (needQueue) { if (delay <= 0) ses.execute(stw); else ses.schedule(stw, delay, unit); } } }
SingletonTask { public void reschedule(long delay, TimeUnit unit) { boolean needQueue = true; SingletonTaskWorker stw = null; synchronized (context) { if (context.taskRunning || context.taskShouldRun) { if (context.taskRunning) { if (delay > 0) { long now = System.nanoTime(); long then = now + TimeUnit.NANOSECONDS.convert(delay, unit); context.waitingTask.nextschedule = then; } else { context.waitingTask.nextschedule = 0; } needQueue = false; } else { context.waitingTask.canceled = true; context.waitingTask = null; } } context.taskShouldRun = true; if (needQueue) { stw = context.waitingTask = new SingletonTaskWorker(this); } } if (needQueue) { if (delay <= 0) ses.execute(stw); else ses.schedule(stw, delay, unit); } } SingletonTask(ScheduledExecutorService ses,
            Runnable task); }
SingletonTask { public void reschedule(long delay, TimeUnit unit) { boolean needQueue = true; SingletonTaskWorker stw = null; synchronized (context) { if (context.taskRunning || context.taskShouldRun) { if (context.taskRunning) { if (delay > 0) { long now = System.nanoTime(); long then = now + TimeUnit.NANOSECONDS.convert(delay, unit); context.waitingTask.nextschedule = then; } else { context.waitingTask.nextschedule = 0; } needQueue = false; } else { context.waitingTask.canceled = true; context.waitingTask = null; } } context.taskShouldRun = true; if (needQueue) { stw = context.waitingTask = new SingletonTaskWorker(this); } } if (needQueue) { if (delay <= 0) ses.execute(stw); else ses.schedule(stw, delay, unit); } } SingletonTask(ScheduledExecutorService ses,
            Runnable task); void reschedule(long delay, TimeUnit unit); }
SingletonTask { public void reschedule(long delay, TimeUnit unit) { boolean needQueue = true; SingletonTaskWorker stw = null; synchronized (context) { if (context.taskRunning || context.taskShouldRun) { if (context.taskRunning) { if (delay > 0) { long now = System.nanoTime(); long then = now + TimeUnit.NANOSECONDS.convert(delay, unit); context.waitingTask.nextschedule = then; } else { context.waitingTask.nextschedule = 0; } needQueue = false; } else { context.waitingTask.canceled = true; context.waitingTask = null; } } context.taskShouldRun = true; if (needQueue) { stw = context.waitingTask = new SingletonTaskWorker(this); } } if (needQueue) { if (delay <= 0) ses.execute(stw); else ses.schedule(stw, delay, unit); } } SingletonTask(ScheduledExecutorService ses,
            Runnable task); void reschedule(long delay, TimeUnit unit);  }