[rabbitmq-discuss] Channel thread safety in Java client
jiri at krutil.com
Tue Jul 5 13:24:08 BST 2011
thanks for that detailed explanation, it definitely helps.
The concept of customizable thread pool and executor you describe sounds
nice. I guess it will be easier and more natural to program against such
The reason I'm interested in how this works is that I'm trying to put
together a vendor-neutral AMQP C++ API with support for async
consumption and I find a lot of inspiration for that in the Java client.
My initial goal is to find a feature set and semantics that can be
mapped to RabbitMQ and Qpid. The API should expose features common for
0-9-1 and 0-10 specs; I'm kind of ignoring AMQP 1.0 for now.
I already have a draft implementation of this API for Qpid 0.7 C++
client. Still not sure if rabbitmq-c has everything I need...
> The current implementation of the Java Client calls the Consumer
> interface on the same thread that the Channel work is done on. This
> means that anything done in the Consumer callbacks is synchronised
> with all the other channel stuff going on, and could potentially block
> it. There are notes on the api-guide pages to warn you about this.
> The QueueingConsumer class basically makes sure that the Consumer
> callbacks do not cause any problems, putting the messages on the
> (dedicated) queue for any (usually the main) thread to access them.
> This means that, even though there may be many consumers defined for a
> Channel, ownership of the Channel is not passed to the 'lib's
> connection thread', and you can continue to use the Channel from the
> main thread, or whatever thread you have allocated to run it from.
> You can ack messages, and anything else you want, too.
> The thing you shouldn't do is to call Channel methods (for the same
> channel) from more than one thread at a time. This is because the
> threading model in the channel is 'challenged'.
> We are currently working on the Consumer and Channel threading
> restrictions -- we want to run all the Consumer callbacks on a thread
> which is distinct from the Connection thread; and allow channels to be
> driven from multiple threads. This would mean it is feasible to do
> most Channel operations from the Consumer callback itself, and from
> any other thread.
> Incidentally, the way our changes are going at the moment, we will
> expose the execution thread pool for Consumer callbacks; and allow the
> user to have control over how many threads are allocated. For
> example, it might be thought sensible to have a single thread per
> channel allocated for Consumer callbacks; but this could mean a large
> penalty for a large number of channels that may be doing very little
> work. Instead we pass work to an Executor (managed so that all the
> work required by a single channel is serialised) which runs it on a
> thread from a pool. The default Executor will use a (fixed) pool of
> 16 threads, but the interface will allow passing in any Executor
> implementation for the Connection.
> I hope this helps. Feedback is welcome.
> Steve Powell (a happy bunny)
More information about the rabbitmq-discuss