private void recover(RecoveredDeletionServiceState state) throws IOException { List<DeletionServiceDeleteTaskProto> taskProtos = state.getTasks(); Map<Integer, DeletionTaskRecoveryInfo> idToInfoMap = new HashMap<Integer, DeletionTaskRecoveryInfo>(taskProtos.size()); Set<Integer> successorTasks = new HashSet<Integer>(); for (DeletionServiceDeleteTaskProto proto : taskProtos) { DeletionTaskRecoveryInfo info = parseTaskProto(proto); idToInfoMap.put(info.task.taskId, info); nextTaskId.set(Math.max(nextTaskId.get(), info.task.taskId)); successorTasks.addAll(info.successorTaskIds); } // restore the task dependencies and schedule the deletion tasks that // have no predecessors final long now = System.currentTimeMillis(); for (DeletionTaskRecoveryInfo info : idToInfoMap.values()) { for (Integer successorId : info.successorTaskIds) { DeletionTaskRecoveryInfo successor = idToInfoMap.get(successorId); if (successor != null) { info.task.addFileDeletionTaskDependency(successor.task); } else { LOG.error( "Unable to locate dependency task for deletion task " + info.task.taskId + " at " + info.task.getSubDir()); } } if (!successorTasks.contains(info.task.taskId)) { long msecTilDeletion = info.deletionTimestamp - now; sched.schedule(info.task, msecTilDeletion, TimeUnit.MILLISECONDS); } } }
public void internalSchedule(TimerJobInstance timerJobInstance) { Date date = timerJobInstance.getTrigger().hasNextFireTime(); Callable<Void> item = (Callable<Void>) timerJobInstance; JDKJobHandle jobHandle = (JDKJobHandle) timerJobInstance.getJobHandle(); long then = date.getTime(); long now = System.currentTimeMillis(); ScheduledFuture<Void> future = null; if (then >= now) { future = scheduler.schedule(item, then - now, TimeUnit.MILLISECONDS); } else { future = scheduler.schedule(item, 0, TimeUnit.MILLISECONDS); } jobHandle.setFuture(future); jobFactoryManager.addTimerJobInstance(timerJobInstance); }
/** @param runFrequency implemented only for TimeUnit granularity - Seconds */ public static void schedule(Runnable runnable, Duration runFrequency, TimerType timerType) { switch (timerType) { case OneTimeRun: long seconds = runFrequency.getSeconds(); if (seconds > 0) executor.schedule(runnable, seconds, TimeUnit.SECONDS); else executor.schedule(runnable, runFrequency.toMillis(), TimeUnit.MILLISECONDS); break; case RepeatRun: executor.scheduleWithFixedDelay( runnable, runFrequency.getSeconds(), runFrequency.getSeconds(), TimeUnit.SECONDS); break; default: throw new UnsupportedOperationException("Unsupported timer pattern."); } }
public ScheduledFuture<?> scheduleAi(Runnable r, long delay) { try { delay = ThreadPoolManager.validateDelay(delay); return _aiScheduledThreadPool.schedule(new RunnableWrapper(r), delay, TimeUnit.MILLISECONDS); } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ } }
/** * Schedules a task. * * @param taskId the task id, used for looking up results and canceling the task * @param task the task * @param recurs <tt>true</tt> if this is a recurring task * @param intervalMillis number of milliseconds between executions of a recurring task, measured * between the end of the last execution and the start of the next * @param delayMillis number of milliseconds to wait before the first execution */ public void schedule( Object taskId, Callable<V> task, boolean recurs, long intervalMillis, long delayMillis) { ZimbraLog.scheduler.debug("Scheduling task %s", taskId); TaskRunner<V> runner = new TaskRunner<V>(taskId, task, recurs, intervalMillis, mCallbacks); runner.mSchedule = mThreadPool.schedule(runner, delayMillis, TimeUnit.MILLISECONDS); mRunnerMap.put(taskId, runner); }
public ScheduledFuture<?> scheduleAi(Runnable r, long delay) { try { if (delay < 0) { delay = 0; } return _aiScheduledThreadPool.schedule(r, delay, TimeUnit.MILLISECONDS); } catch (RejectedExecutionException e) { return null; /* shutdown, ignore */ } }
private void scheduleDiskCacheFlush() { // If we already have a flush scheduled, cancel it if (null != mDiskCacheFuture) { mDiskCacheFuture.cancel(false); } // Schedule a flush mDiskCacheFuture = mDiskCacheFlusherExecutor.schedule( mDiskCacheFlusherRunnable, DISK_CACHE_FLUSH_DELAY_SECS, TimeUnit.SECONDS); }
final Future<?> schedule(Runnable task, long timeout, TimeUnit unit) { try { return timeoutExecutor.schedule(task, timeout, unit); } catch (RejectedExecutionException rej) { if (terminateInitiated) { // no timeout scheduled as group is terminating return null; } throw new AssertionError(rej); } }
/** * Delete the path(s) as this user. * * @param user The user to delete as, or the JVM user if null * @param subDir the sub directory name * @param baseDirs the base directories which contains the subDir's */ public void delete(String user, Path subDir, Path... baseDirs) { // TODO if parent owned by NM, rename within parent inline if (debugDelay != -1) { List<Path> baseDirList = null; if (baseDirs != null && baseDirs.length != 0) { baseDirList = Arrays.asList(baseDirs); } FileDeletionTask task = new FileDeletionTask(this, user, subDir, baseDirList); recordDeletionTaskInStateStore(task); sched.schedule(task, debugDelay, TimeUnit.SECONDS); } }
private void reparseInSeparateThread() { if (scheduledOperation != null) { scheduledOperation.cancel(true); } final Runnable parsingRunnable = new Runnable() { @Override public void run() { reparse(); parsingSemaphore.release(); } }; scheduledOperation = executor.schedule(parsingRunnable, DELAY, TimeUnit.MILLISECONDS); }
@Override public void handle( final HttpRequest request, final HttpAsyncExchange httpexchange, final HttpContext context) { executor.schedule( new Runnable() { @Override public void run() { HttpResponse response = httpexchange.getResponse(); response.setStatusCode(HttpStatus.SC_OK); response.setEntity( new NStringEntity(("Slow hello world"), ContentType.create("text/html", "UTF-8"))); httpexchange.submitResponse(); } }, 50, TimeUnit.MILLISECONDS); }
void test(String[] args) throws Throwable { ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(0); Runnable task = new Runnable() { public void run() { taskRun = true; } }; check(pool.getCorePoolSize() == 0); pool.schedule(task, 1, TimeUnit.SECONDS); pool.shutdown(); check(pool.awaitTermination(20L, TimeUnit.SECONDS)); check(pool.getCorePoolSize() == 0); check(taskRun); }
public static void scheduleForCRON(Job job) { if (job.getClass().isAnnotationPresent(On.class)) { String cron = ((On) (job.getClass().getAnnotation(On.class))).value(); if (cron.startsWith("cron.")) { cron = Play.configuration.getProperty(cron); } if (cron != null && !cron.equals("")) { try { Date now = new Date(); Date nextDate = Time.parseCRONExpression(cron); long delay = nextDate.getTime() - now.getTime(); executor.schedule((Callable) job, delay, TimeUnit.MILLISECONDS); job.executor = executor; } catch (Exception ex) { throw new UnexpectedException(ex); } } else { Logger.info("Skipping job %s, cron expression is not defined", job.getClass().getName()); } } }
private synchronized void scheduleRemoval() { if (scheduledExpiration != null && scheduledExpiration.isAfterNow()) { return; } DateTime newExpiration = scheduledExpiration; do { newExpiration = askChatter(DateTime.class, new RemoveAfter(newExpiration)); } while (newExpiration != null && newExpiration.isBeforeNow()); scheduledExpiration = newExpiration; if (scheduledExpiration != null) { autoremover.schedule( this, scheduledExpiration.getMillis() - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } }
public void schedule(long taskId, long deadlineId, long delay, DeadlineType type) { ScheduledFuture<ScheduledTaskDeadline> scheduled = scheduler.schedule( new ScheduledTaskDeadline(taskId, deadlineId, type), delay, TimeUnit.MILLISECONDS); List<ScheduledFuture<ScheduledTaskDeadline>> knownFutures = null; if (type == DeadlineType.START) { knownFutures = this.startScheduledTaskDeadlines.get(taskId); } else if (type == DeadlineType.END) { knownFutures = this.endScheduledTaskDeadlines.get(taskId); } if (knownFutures == null) { knownFutures = new CopyOnWriteArrayList<ScheduledFuture<ScheduledTaskDeadline>>(); } knownFutures.add(scheduled); if (type == DeadlineType.START) { this.startScheduledTaskDeadlines.put(taskId, knownFutures); } else if (type == DeadlineType.END) { this.endScheduledTaskDeadlines.put(taskId, knownFutures); } }
public static <V> void scheduleForCRON(Job<V> job) { if (!job.getClass().isAnnotationPresent(On.class)) { return; } String cron = job.getClass().getAnnotation(On.class).value(); if (cron.startsWith("cron.")) { cron = Play.configuration.getProperty(cron); } cron = Expression.evaluate(cron, cron).toString(); if (cron == null || "".equals(cron) || "never".equalsIgnoreCase(cron)) { if (Logger.isEnabledFor("INFO")) Logger.info("Skipping job %s, cron expression is not defined", job.getClass().getName()); return; } try { Date now = new Date(); cron = Expression.evaluate(cron, cron).toString(); CronExpression cronExp = new CronExpression(cron); Date nextDate = cronExp.getNextValidTimeAfter(now); if (nextDate == null) { if (Logger.isEnabledFor("WARN")) Logger.warn( "The cron expression for job %s doesn't have any match in the future, will never be executed", job.getClass().getName()); return; } if (nextDate.equals(job.nextPlannedExecution)) { // Bug #13: avoid running the job twice for the same time // (happens when we end up running the job a few minutes before the planned time) Date nextInvalid = cronExp.getNextInvalidTimeAfter(nextDate); nextDate = cronExp.getNextValidTimeAfter(nextInvalid); } job.nextPlannedExecution = nextDate; executor.schedule( (Callable<V>) job, nextDate.getTime() - now.getTime(), TimeUnit.MILLISECONDS); job.executor = executor; } catch (Exception ex) { throw new UnexpectedException(ex); } }
private void startDelayedPersistTimer(int maxDelaySec, final AuthenticationInfo subject) { synchronized (this) { if (delayedPersist != null) { return; } delayedPersist = delayedPersistThreadPool.schedule( new Runnable() { @Override public void run() { try { persist(subject); } catch (IOException e) { logger.error(e.getMessage(), e); } } }, maxDelaySec, TimeUnit.SECONDS); } }
/** * Executes {@code command} with zero required delay. This has effect equivalent to {@link * #schedule(Runnable,long,TimeUnit) schedule(command, 0, anyUnit)}. Note that inspections of the * queue and of the list returned by {@code shutdownNow} will access the zero-delayed {@link * ScheduledFuture}, not the {@code command} itself. * * <p>A consequence of the use of {@code ScheduledFuture} objects is that {@link * ThreadPoolExecutor#afterExecute afterExecute} is always called with a null second {@code * Throwable} argument, even if the {@code command} terminated abruptly. Instead, the {@code * Throwable} thrown by such a task can be obtained via {@link Future#get}. * * @throws RejectedExecutionException at discretion of {@code RejectedExecutionHandler}, if the * task cannot be accepted for execution because the executor has been shut down * @throws NullPointerException {@inheritDoc} */ public void execute(Runnable command) { schedule(command, 0, NANOSECONDS); }
public void scheduleFileDeletionTask(FileDeletionTask fileDeletionTask) { if (debugDelay != -1) { recordDeletionTaskInStateStore(fileDeletionTask); sched.schedule(fileDeletionTask, debugDelay, TimeUnit.SECONDS); } }
public void schedule(Runnable event, long delay) { scheduler.schedule(event, delay, TimeUnit.MILLISECONDS); }
public ScheduledFuture<?> schedule(TimeValue delay, String name, Runnable command) { if (!Names.SAME.equals(name)) { command = new ThreadedRunnable(command, executor(name)); } return scheduler.schedule(command, delay.millis(), TimeUnit.MILLISECONDS); }
private ScheduledFuture schedule(TimedEvent t, long timeoutMs) { return _executor.schedule(t, timeoutMs, TimeUnit.MILLISECONDS); }
/** * Run the code in a new thread after a delay * * @param invocation The code to run * @param millis The time to wait before, in milliseconds * @return The future object, to know when the task is completed */ public static Future<?> invoke(final Invocation invocation, long millis) { Monitor monitor = MonitorFactory.getMonitor("Invocation queue", "elmts."); monitor.add(executor.getQueue().size()); return executor.schedule(invocation, millis, TimeUnit.MILLISECONDS); }
@Override public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { return m_executor.schedule(command, delay, unit); }
@Test @Parameters @SuppressWarnings("unchecked") public final void testDelayed( int minDelay, int maxDelay, float lossChance, float dupChance, int executeInterval, long executeTime, boolean retransmit) throws InterruptedException { /* * Record phase */ final UnreliableQueue<Packet<Long>> aToB = new UnreliableQueue<Packet<Long>>( queueListenerAtoB, minDelay, maxDelay, lossChance, dupChance); final UnreliableQueue<Packet<Long>> bToA = new UnreliableQueue<Packet<Long>>( queueListenerBtoA, minDelay, maxDelay, lossChance, dupChance); ProtocolListener<Long> listenerA = DEBUG ? new DebugProtocolListener<Long>(protocolListenerA, Logger.getConsoleLogger("A")) : protocolListenerA; final TestHost<Long> hostA = new TestHost<Long>( hostListenerA, new LongDataGenerator(), bToA, aToB, new ProtocolConfig<Long>(listenerA), DEBUG ? "A" : null); final List<Long> sentA = new ArrayList<Long>(); final List<Long> lostSentA = new ArrayList<Long>(); final List<Long> dupedSentA = new ArrayList<Long>(); final List<Long> receivedA = new ArrayList<Long>(); final List<Long> ackedA = new ArrayList<Long>(); final List<Long> notAckedA = new ArrayList<Long>(); final List<Long> orderedA = new ArrayList<Long>(); final List<Long> unorderedA = new ArrayList<Long>(); final List<Long> retransmitsA = new ArrayList<Long>(); ProtocolListener<Long> listenerB = DEBUG ? new DebugProtocolListener<Long>(protocolListenerB, Logger.getConsoleLogger("B")) : protocolListenerB; final TestHost<Long> hostB = new TestHost<Long>( hostListenerB, new LongDataGenerator(), aToB, bToA, new ProtocolConfig<Long>(listenerB), DEBUG ? "B" : null); final List<Long> sentB = new ArrayList<Long>(); final List<Long> lostSentB = new ArrayList<Long>(); final List<Long> dupedSentB = new ArrayList<Long>(); final List<Long> receivedB = new ArrayList<Long>(); final List<Long> ackedB = new ArrayList<Long>(); final List<Long> notAckedB = new ArrayList<Long>(); final List<Long> orderedB = new ArrayList<Long>(); final List<Long> unorderedB = new ArrayList<Long>(); final List<Long> retransmitsB = new ArrayList<Long>(); new NonStrictExpectations() { { hostListenerA.notifyReceived(withCapture(receivedA)); hostListenerA.notifySent(withCapture(sentA)); hostListenerA.notifyRetransmitted(withCapture(retransmitsA)); protocolListenerA.handleAckedData(anyShort, withCapture(ackedA)); protocolListenerA.handleUnackedData(anyShort, withCapture(notAckedA)); protocolListenerA.handleOrderedData(anyShort, withCapture(orderedA)); protocolListenerA.handleUnorderedData(anyShort, withCapture(unorderedA)); } }; new NonStrictExpectations() { { hostListenerB.notifyReceived(withCapture(receivedB)); hostListenerB.notifySent(withCapture(sentB)); hostListenerB.notifyRetransmitted(withCapture(retransmitsB)); protocolListenerB.handleAckedData(anyShort, withCapture(ackedB)); protocolListenerB.handleUnackedData(anyShort, withCapture(notAckedB)); protocolListenerB.handleOrderedData(anyShort, withCapture(orderedB)); protocolListenerB.handleUnorderedData(anyShort, withCapture(unorderedB)); } }; new NonStrictExpectations() { { queueListenerAtoB.notifyDuplicate((Packet<Long>) any); result = new Delegate<Packet<Long>>() { @SuppressWarnings("unused") void delegate(Packet<Long> dup) { for (Metadata<Long> metadata : dup.getMetadatas()) { dupedSentA.add(metadata.getData()); if (DEBUG) System.out.println("[A-dupedSent]: " + metadata.getData()); } } }; queueListenerAtoB.notifyLoss((Packet<Long>) any); result = new Delegate<Packet<Long>>() { @SuppressWarnings("unused") void delegate(Packet<Long> loss) { for (Metadata<Long> metadata : loss.getMetadatas()) { lostSentA.add(metadata.getData()); if (DEBUG) System.out.println("[A-lostSent]: " + metadata.getData()); } } }; queueListenerBtoA.notifyDuplicate((Packet<Long>) any); result = new Delegate<Packet<Long>>() { @SuppressWarnings("unused") void delegate(Packet<Long> dup) { for (Metadata<Long> metadata : dup.getMetadatas()) { dupedSentB.add(metadata.getData()); if (DEBUG) System.out.println("[B-dupedSent]: " + metadata.getData()); } } }; queueListenerBtoA.notifyLoss((Packet<Long>) any); result = new Delegate<Packet<Long>>() { @SuppressWarnings("unused") void delegate(Packet<Long> loss) { for (Metadata<Long> metadata : loss.getMetadatas()) { lostSentB.add(metadata.getData()); if (DEBUG) System.out.println("[B-lostSent]: " + metadata.getData()); } } }; } }; /* * Replay phase */ // play it for a longer interval executor.scheduleAtFixedRate(hostA, 0, executeInterval, TimeUnit.MILLISECONDS); executor.scheduleAtFixedRate( hostB, executeInterval / 2, executeInterval, TimeUnit.MILLISECONDS); executor.schedule( new Runnable() { @Override public void run() { // enable reliable queue mode for final messages aToB.setDupChance(0f); aToB.setLossChance(0f); aToB.setMinDelay(0L); aToB.setMaxDelay(0L); bToA.setDupChance(0f); bToA.setLossChance(0f); bToA.setMinDelay(0L); bToA.setMaxDelay(0L); } }, executeTime - executeTime / 10, TimeUnit.SECONDS); executor.awaitTermination(executeTime, TimeUnit.SECONDS); executor.shutdown(); executor.awaitTermination(executeInterval * 2 + maxDelay * 2, TimeUnit.MILLISECONDS); // let pending messages finish Thread.sleep(maxDelay * 2); hostA.receive(); hostB.receive(); hostA.send(); hostB.send(); Thread.sleep(maxDelay * 2); // wait for queue to make all elements available hostA.receive(); hostB.receive(); System.out.println(); /* * Verify phase */ for (Long item : notAckedA) assertTrue("notAcked data should not have been acked", !ackedA.contains(item)); for (Long item : notAckedB) assertTrue("notAcked data should not have been acked", !ackedB.contains(item)); for (Long item : retransmitsA) assertTrue("retransmitted data should have been sent from sender", sentA.contains(item)); for (Long item : retransmitsB) assertTrue("retransmitted data should have been sent from sender", sentB.contains(item)); for (Long item : lostSentA) assertTrue("over medium lost data should have been sent from sender", sentA.contains(item)); for (Long item : lostSentB) assertTrue("over medium lost data should have been sent from sender", sentB.contains(item)); for (Long item : dupedSentA) assertTrue( "over medium duplicated data should have been sent from sender", sentA.contains(item)); for (Long item : dupedSentB) assertTrue( "over medium duplicated data should have been sent from sender", sentB.contains(item)); Long lastItem = null; for (Long item : orderedA) { assertTrue("orderly received data should have been sent from sender", sentB.contains(item)); if (lastItem != null) { assertTrue("ordered data should be ordered", item > lastItem); } lastItem = item; } lastItem = null; for (Long item : orderedB) { assertTrue("orderly received data should have been sent from sender", sentA.contains(item)); if (lastItem != null) { assertTrue("ordered data should be ordered", item > lastItem); } lastItem = item; } lastItem = null; for (Long item : unorderedA) { assertTrue("unorderly received data should have been sent from sender", sentB.contains(item)); if (lastItem != null) { assertTrue("unordered data should be ordered", item > lastItem); } lastItem = item; assertTrue("unordered data should not have been orderly received", !orderedA.contains(item)); // The following assertions can not be guaranteed, since there may be multiple unordered // events and multiple holes until an ordered event occurs // Long pred = item; // do { // pred--; // } while(unorderedA.contains(pred)); // Long succ = item; // do { // succ++; // } while(unorderedA.contains(succ)); // assertTrue("ordered data contains predecessor of unorderedData", // orderedA.contains(pred)); // assertTrue("ordered data contains successor of unorderedData", orderedA.contains(succ)); } lastItem = null; for (Long item : unorderedB) { assertTrue("orderly received data should have been sent from sender", sentA.contains(item)); if (lastItem != null) { assertTrue("unordered data should be ordered", item > lastItem); } lastItem = item; assertTrue("unordered data should not have been orderly received", !orderedB.contains(item)); // The following assertions can not be guaranteed, since there may be multiple unordered // events and multiple holes until an ordered event occurs // Long pred = item; // do { // pred--; // } while(unorderedB.contains(pred)); // Long succ = item; // do { // succ++; // } while(unorderedB.contains(succ)); // assertTrue("ordered data contains predecessor of unorderedData", // orderedB.contains(pred)); // assertTrue("ordered data contains successor of unorderedData", orderedB.contains(succ)); } // the following addition of "magic constants" is due to the scheduling procedure of the very // last messages assertEquals( "all messages from A must be received at B", receivedB.size(), sentA.size() - lostSentA.size() + dupedSentA.size()); assertEquals( "all messages from A must be acked", ackedA.size(), sentA.size() - retransmitsA.size() - notAckedA.size() - 1); assertEquals( "all messages from A must be ordered at B", orderedB.size(), sentA.size() - retransmitsA.size() - unorderedB.size()); // the following addition of "magic constants" is due to the scheduling procedure of the very // last messages assertEquals( "all messages from B must be received at A", receivedA.size(), sentB.size() - lostSentB.size() + dupedSentB.size()); assertEquals( "all messages from B must be acked", ackedB.size(), sentB.size() - retransmitsB.size() - notAckedB.size() - 1); assertEquals( "all messages from B must be ordered at A", orderedA.size(), sentB.size() - retransmitsB.size() - unorderedA.size()); if (lossChance == 0f) { assertEquals("no lost packets", 0, lostSentB.size()); assertEquals("no lost packets", 0, lostSentA.size()); } if (dupChance == 0f) { assertEquals("no duped packets", 0, dupedSentB.size()); assertEquals("no duped packets", 0, dupedSentA.size()); } if (retransmit || lossChance == 0f) { new Verifications() { { protocolListenerA.handleUnackedData(anyShort, anyLong); times = 0; protocolListenerA.handleUnorderedData(anyShort, anyLong); times = 0; } }; new Verifications() { { protocolListenerB.handleUnackedData(anyShort, anyLong); times = 0; protocolListenerB.handleUnorderedData(anyShort, anyLong); times = 0; } }; assertEquals("all packets acked", 0, notAckedA.size()); assertEquals("all packets ordered", 0, unorderedA.size()); assertEquals("all packets acked", 0, notAckedB.size()); assertEquals("all packets ordered", 0, unorderedB.size()); } }
@Override public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { return m_executor.schedule(callable, delay, unit); }
/** * Run a set of threads making changes to the deprecations concurrently with another set of * threads calling get() and set() on Configuration objects. */ @SuppressWarnings("deprecation") @Test(timeout = 60000) public void testConcurrentDeprecateAndManipulate() throws Exception { final int NUM_THREAD_IDS = 10; final int NUM_KEYS_PER_THREAD = 1000; ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor( 2 * NUM_THREAD_IDS, new ThreadFactoryBuilder() .setDaemon(true) .setNameFormat("testConcurrentDeprecateAndManipulate modification thread %d") .build()); final CountDownLatch latch = new CountDownLatch(1); final AtomicInteger highestModificationThreadId = new AtomicInteger(1); List<Future<Void>> futures = new LinkedList<Future<Void>>(); for (int i = 0; i < NUM_THREAD_IDS; i++) { futures.add( executor.schedule( new Callable<Void>() { @Override public Void call() throws Exception { latch.await(); int threadIndex = highestModificationThreadId.addAndGet(1); for (int i = 0; i < NUM_KEYS_PER_THREAD; i++) { String testKey = getTestKeyName(threadIndex, i); String testNewKey = testKey + ".new"; Configuration.addDeprecations( new DeprecationDelta[] {new DeprecationDelta(testKey, testNewKey)}); } return null; } }, 0, TimeUnit.SECONDS)); } final AtomicInteger highestAccessThreadId = new AtomicInteger(1); for (int i = 0; i < NUM_THREAD_IDS; i++) { futures.add( executor.schedule( new Callable<Void>() { @Override public Void call() throws Exception { Configuration conf = new Configuration(); latch.await(); int threadIndex = highestAccessThreadId.addAndGet(1); for (int i = 0; i < NUM_KEYS_PER_THREAD; i++) { String testNewKey = getTestKeyName(threadIndex, i) + ".new"; String value = "value." + threadIndex + "." + i; conf.set(testNewKey, value); Assert.assertEquals(value, conf.get(testNewKey)); } return null; } }, 0, TimeUnit.SECONDS)); } latch.countDown(); // allow all threads to proceed for (Future<Void> future : futures) { Uninterruptibles.getUninterruptibly(future); } }
@Override public synchronized void start(Runnable runnable) { executor.schedule(runnable, delay, timeUnit); }