private synchronized void schedule(ExecutionBuilder.TaskWrapper wrapper) { // As tasks often create a loop by calling itself (e.g. BackgroundLoop), we drop // scheduled tasks if the async framework is no longer running, as the tasks would be rejected and // dropped anyway... if (!running) { return; } Long lastInvocation = scheduleTable.get(wrapper.synchronizer); if (lastInvocation == null || (System.currentTimeMillis() - lastInvocation) > wrapper.intervalMinLength) { executeNow(wrapper); } else { if (dropIfAlreadyScheduled(wrapper)) { if (LOG.isFINE()) { LOG.FINE( "Dropping a scheduled task (%s), as for its synchronizer (%s) another task is already scheduled", wrapper.runnable, wrapper.synchronizer); } return; } wrapper.waitUntil = lastInvocation + wrapper.intervalMinLength; addToSchedulerQueue(wrapper); wakeSchedulerLoop(); } }