<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Darren,<br><br>That repo is out of date. All work on this bug moved to <a href="http://hg.rabbitmq.com/">hg.rabbitmq.com</a>.<br><br>In the latest patch all consumers get the new threading behaviour and the JavaDoc is updated to reflect that.<br><br>I'm pretty concerned about sending callback methods to consumers on different threads. As a bare minimum we have to ensure that handleDelivery is never called out of order. <br><br>Not just that but I think we need to ensure that exit from handleDelivery happens-before each subsequent entry into handleDelivery on a given consumer. <br><br>This prevents us from using a rudimentary producer/consumer model. Such a model would allow for multiple hD calls for a given consumer to run concurrently.<br><br>Beyond just a single dispatch, I'm happy with a model that maintains a pool of threads but assigns consumers to one thread or another.<br><br>I'm concerned about the impact on user code of allowing dispatches to a consumer in multiple threads.<br><br>Rob<br><div><div>On 2 Oct 2010, at 21:55, darr wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div><br><a href="http://bitbucket.org/robharrop/rabbitmq-java-client/changeset/ea463bbd4871">http://bitbucket.org/robharrop/rabbitmq-java-client/changeset/ea463bbd4871</a><br>That's the commit I'm referencing. I hope it's the right one.<br><br>It looks like you're breaking the contract of Consumer a little bit when you<br>move this off of the Connection's thread (since that's what's documented). <br>This is a Good Thing, because, as you note, implementations of consumer can<br>now call blocking methods on Connection and Channel. However, this has a<br>down side in that only some consumers are permitted to call blocking methods<br>-- those that use DispatchingConsumer. Other consumers are guaranteed to<br>have their methods called from the Connection thread.<br><br>So this is a bit of extra complexity for implementations of Consumer to<br>consider. Given that implementors of Consumer already need to think of<br>these things, you might re-evaluate the idea that consumers require all of<br>their methods to be called from a single thread. The mechanics of making a<br>consumer thread-safe seem very manageable. There's not a lot of interaction<br>between the methods and very little state.<br><br>However, if you share my concern about breaking the contract of Consumer,<br>you could introduce another interface (ConcurrentConsumer) which specifies<br>exactly the requirements of its implementations and modify<br>DispachingConsumer to accept only ConcurrentConsumer.<br><br>As for the possibility of ConnectionFactory.setDispatchThreadCount(int), I<br>think if I set that to some value greater than one, and had only a single<br>consumer, I would expect handleDelivery to be called from multiple threads. <br>I think we might be safer making DispatchingConsumer the sole party<br>responsible for these things and it can accept an Executor on construction.<br>Then the user can decide if all consumers can safely share the same set of<br>threads, or if they need some other behavior.<br><br>What do you think?<br><br>Thanks,<br>Darren.<br><br><br>Rob Harrop-5 wrote:<br><blockquote type="cite"><br></blockquote><blockquote type="cite">Recently I pushed branch bug18384 that changes the way callbacks are sent<br></blockquote><blockquote type="cite">to Consumer implementations.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Following this change, the Connection maintains a dispatch thread that is<br></blockquote><blockquote type="cite">used to send callbacks to the Consumers. This frees Consumers call<br></blockquote><blockquote type="cite">blocking methods on the Connection and Channel.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">A question came up on Twitter about making this configurable, allowing for<br></blockquote><blockquote type="cite">a custom Executor to be plugged into the ConnectionFactory. I wanted to<br></blockquote><blockquote type="cite">outline why this is complicated, discuss a possible implementation and see<br></blockquote><blockquote type="cite">if there is much interest.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">First off, we should establish that each Consumer should only receive<br></blockquote><blockquote type="cite">callbacks in a single thread. If this is not the case, then chaos will<br></blockquote><blockquote type="cite">ensue and Consumers will need to worry about their own thread safety<br></blockquote><blockquote type="cite">beyond that of initialisation safety.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">With only a single dispatch thread for all Consumers, this Consumer-Thread<br></blockquote><blockquote type="cite">pairing is easy honoured.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">When we introduce multiple threads, we have to ensure that each Consumer<br></blockquote><blockquote type="cite">is paired with only one thread. When using the Executor abstraction, this<br></blockquote><blockquote type="cite">prevents each callback dispatch from being wrapped up in a Runnable and<br></blockquote><blockquote type="cite">sent to Executor, because you cannot guarantee which thread will be used.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">To get around this, the Executor can be set to run 'n' long-running tasks<br></blockquote><blockquote type="cite">(n being the number of threads in the Executor). Each of these tasks pulls<br></blockquote><blockquote type="cite">dispatch instructions off a queue and executes them. Each Consumer is<br></blockquote><blockquote type="cite">paired with one dispatch instruction queue, probably assigned on a<br></blockquote><blockquote type="cite">round-robin basis. This is not too complicated and will provide simple<br></blockquote><blockquote type="cite">balancing of dispatch load across the threads in the Executor.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Now, there are still some problems:<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">1. The number of threads in an Executor is not necessarily fixed (as with<br></blockquote><blockquote type="cite">ThreadPoolExecutor).<br></blockquote><blockquote type="cite">2. There is no way, via Executor or ExecutorService to find out how many<br></blockquote><blockquote type="cite">threads there are. Thus, we cannot know how many dispatch instruction<br></blockquote><blockquote type="cite">queues to create.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">However, we can certainly introduce a<br></blockquote><blockquote type="cite">ConnectionFactory.setDispatchThreadCount(int). Behind the scenes this will<br></blockquote><blockquote type="cite">create an Executors.newFixedThreadPool() and the correct number of<br></blockquote><blockquote type="cite">dispatch queues and dispatch tasks.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">I'm interested in hearing if anyone thinks I'm overlooking some simpler<br></blockquote><blockquote type="cite">way of solving this, and indeed if this is even worth solving.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Regards,<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Rob<br></blockquote><blockquote type="cite">_______________________________________________<br></blockquote><blockquote type="cite">rabbitmq-discuss mailing list<br></blockquote><blockquote type="cite">rabbitmq-discuss@lists.rabbitmq.com<br></blockquote><blockquote type="cite">https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite"><br></blockquote><br>-- <br>View this message in context: http://old.nabble.com/Multi-threaded-Dispatch-in-Java-Client-tp29860178p29868134.html<br>Sent from the RabbitMQ mailing list archive at Nabble.com.<br><br>_______________________________________________<br>rabbitmq-discuss mailing list<br>rabbitmq-discuss@lists.rabbitmq.com<br>https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss<br></div></blockquote></div><br></body></html>