@Override public void run() { try { boolean running = true; while (running) { try { // block on event availability ThreadBoundEvent event = queue.take(); // add to the batch, and see if we can add more batch.add(event); if (maxBatchSize > 0) { queue.drainTo(batch, maxBatchSize); } // check for the stop condition (and remove it) // treat batches of 1 (the most common case) specially if (batch.size() > 1) { ListIterator<ThreadBoundEvent> itr = batch.listIterator(); while (itr.hasNext()) { ThreadBoundEvent next = itr.next(); if (next.getClass().equals(ShutdownTask.class)) { running = false; ((ShutdownTask) next).latch.countDown(); itr.remove(); } } eventProcessor.process(batch); } else { // just the one event, no need to iterate if (event.getClass().equals(ShutdownTask.class)) { running = false; ((ShutdownTask) event).latch.countDown(); } else { eventProcessor.process(batch); } } } catch (InterruptedException e) { LOG.warn( String.format( "Consumer on queue %s interrupted.", Thread.currentThread().getName())); // ignore } catch (Throwable exception) { LOG.error( String.format( "exception on queue %s while executing events", Thread.currentThread().getName()), exception); } finally { // reset the batch batch.clear(); } } } catch (Throwable unexpectedThrowable) { // we observed some cases where trying to log the inner exception threw an error // don't use the logger here as that seems to be causing the problem in the first place System.err.println("Caught and unexpected Throwable while logging"); System.err.println( "This problem happens when jar files change at runtime, JVM might be UNSTABLE"); unexpectedThrowable.printStackTrace(System.err); } }
/** * Schedule a runnable for execution. * * @param event The runnable to execute */ public void execute(ThreadBoundEvent event) { if (shuttingDown.get()) { throw new RejectedExecutionException("The system is shutting down."); } int bucket = getBucket(event.getKey()); BlockingQueue<ThreadBoundEvent> queue = queues.get(bucket); queue.add(event); }