I've trouble understanding the differences and recommended usage of the dispatchers in Akka 2. I think I understand how the BalancingDispatcher and the CallingThreadDispatcher behave but I have no idea about the Dispatcher and PinnedDispatcher.
I don't understand the concepts of Sharability
and Bulkheading
, either.
I believe Sharability refers to the number/type of actors that can share a particular type of dispatcher. I'm not sure on bulkheading, but I'm going to assume it refers to some sort of actor partitioning where you only want one actor to "own" a thread.
Here are the descriptions from the code/scaladoc comments for the various dispatcher types. If there is more clarification needed, please describe what is unclear:
Dispatcher:
The event-based Dispatcher
binds a set of Actors to a thread pool backed up by a BlockingQueue
.
BalancingDispatcher:
An executor based event driven dispatcher which will try to redistribute work from busy actors to idle actors. It is assumed that all actors using the same instance of this dispatcher can process all messages that have been sent to one of the actors. I.e. the actors belong to a pool of actors, and to the client there is no guarantee about which actor instance actually processes a given message.
Although the technique used in this implementation is commonly known as "work stealing", the actual implementation is probably best described as "work donating" because the actor of which work is being stolen takes the initiative.
PinnedDispatcher:
Dedicates a unique thread for each actor passed in as reference. Served through its messageQueue.
CallingThreadDispatcher (in akka.testkit):
Dispatcher which runs invocations on the current thread only. This dispatcher does not create any new threads, but it can be used from different threads concurrently for the same actor. The dispatch strategy is to run on the current thread unless the target actor is either suspended or already running on the current thread (if it is running on a different thread, then this thread will block until that other invocation is finished); if the invocation is not run, it is queued in a thread-local queue to be executed once the active invocation further up the call stack finishes. This leads to completely deterministic execution order if only one thread is used.
Suspending and resuming are global actions for one actor, meaning they can affect different threads, which leads to complications. If messages are queued (thread-locally) during the suspended period, the only thread to run them upon resume is the thread actually calling the resume method. Hence, all thread-local queues which are not currently being drained (possible, since suspend-queue-resume might happen entirely during an invocation on a different thread) are scooped up into the current thread-local queue which is then executed. It is possible to suspend an actor from within its call stack.
Dispatcher is the default implementation.
PinnedDispatcher has one thread per actor, hence the threads are pinned to their actors.
Sharability means what restrictions apply if multiple actors want to use the same dispatcher instance.
Bulkheading means isolating sections from each other - according to Wikipedia.