A thread-safe queue of listeners, each with an associated Executor, that guarantees
that every Runnable that is added will be
executed in the same order that it was added and also that
execution is delayed until the next call to execute. This is particularly useful if
you need to ensure that listeners are not executed with a lock held.

While similar, this is different than ExecutionList which makes much looser guarantees
around ordering and has a notion of state (the executed bit) that this class does not have.

Listeners are queued by calling add and flushed on calls to execute().
Because calls to add may be concurrent with calls to execute there is no
guarantee that the queue will be empty after calling execute.

Exceptions thrown by a listener will be propagated up to the executor. Any exception thrown
during Executor.execute (e.g., a RejectedExecutionException or an exception
thrown by inline execution) will be caught and
logged.

Executes all listeners in the queue. However, note that listeners added concurrently with this
method may be executed as part of this call or not, so there is no guarantee that the queue is
empty after calling this method.