public void execute(@Nonnull final HttpSession httpSession, @Nonnull final Runnable runnable)
    {
        final StreamID key = httpSession.getStreamID();

        Log.trace("Scheduling runnable for session {}", key);
        final CompletableFuture<Void> future = dispatchQueues.compute(key, (streamID, queue) -> (queue == null)
            ? CompletableFuture.runAsync(runnable, this.stanzaWorkerPool)
            : queue.thenRunAsync(runnable, this.stanzaWorkerPool));

        // Clean up the dispatch queue after execution.
        future.whenComplete((r,e) -> {
            // Optimistic check to avoid locking if not a match.
            if (dispatchQueues.get(key) == future) {
                dispatchQueues.remove(key);
            }
        });
    }
Executes a Runnable in the thread pool that is used for processing stanzas received over BOSH.

Tasks can be executed in parallel, but tasks for the same httpSession are executed serially (in the order in
which they were provided).

@param httpSession The session for which to execute a task
@param runnable The task to execute.
@see <a href="https://stackoverflow.com/a/29893297/189203">Based on this approach by Ben Manes</a>
xmppserver/src/main/java/org/jivesoftware/openfire/http/HttpSessionManager.java