public void run() { HashMap<Queue, LinkedList<MessageReference>> refs = new HashMap<Queue, LinkedList<MessageReference>>(); runnables.remove(deliveryTime); final long now = System.currentTimeMillis(); if (now < deliveryTime) { // Ohhhh... blame it on the OS // on some OSes (so far Windows only) the precision of the scheduled executor could // eventually give // an executor call earlier than it was supposed... // for that reason we will schedule it again so no messages are lost! // we can't just assume deliveryTime here as we could deliver earlier than what we are // supposed to // this is basically a hack to work around an OS or JDK bug! if (trace) { ActiveMQServerLogger.LOGGER.trace( "Scheduler is working around OS imprecisions on " + "timing and re-scheduling an executor. now=" + now + " and deliveryTime=" + deliveryTime); } ScheduledDeliveryHandlerImpl.this.scheduleDelivery(deliveryTime); } if (ScheduledDeliveryHandlerImpl.trace) { ActiveMQServerLogger.LOGGER.trace( "Is it " + System.currentTimeMillis() + " now and we are running deliveryTime = " + deliveryTime); } synchronized (scheduledReferences) { Iterator<RefScheduled> iter = scheduledReferences.iterator(); while (iter.hasNext()) { MessageReference reference = iter.next().getRef(); if (reference.getScheduledDeliveryTime() > now) { // We will delivery as long as there are messages to be delivered break; } iter.remove(); reference.setScheduledDeliveryTime(0); LinkedList<MessageReference> references = refs.get(reference.getQueue()); if (references == null) { references = new LinkedList<MessageReference>(); refs.put(reference.getQueue(), references); } if (ScheduledDeliveryHandlerImpl.trace) { ActiveMQServerLogger.LOGGER.trace( "sending message " + reference + " to delivery, deliveryTime = " + deliveryTime); } references.addFirst(reference); } if (ScheduledDeliveryHandlerImpl.trace) { ActiveMQServerLogger.LOGGER.trace("Finished loop on deliveryTime = " + deliveryTime); } } for (Map.Entry<Queue, LinkedList<MessageReference>> entry : refs.entrySet()) { Queue queue = entry.getKey(); LinkedList<MessageReference> list = entry.getValue(); if (trace) { ActiveMQServerLogger.LOGGER.trace( "Delivering " + list.size() + " elements on list to queue " + queue); } queue.addHead(list); } // Just to speed up GC refs.clear(); }