views:

74

answers:

2

I have a workflow that I want to looks something like this:

                                         / Worker 1 \
=Request Channel= -> [Holding Queue|||] -> Worker 2 -> =Response Channel=
                                         \ Worker 3 /

That is:

  • Requests come in and they enter a FIFO queue
  • Identical workers then pick up tasks from the queue
  • At any given time any worker may work only one task
  • When a worker is free and the holding queue is non-empty the worker should immediately pick up another task
  • When tasks are complete, a worker places the result on the Response Channel

I know there are QueueChannels in Spring Integration, but these channels require polling (which seems suboptimal). In particular, if a worker can be busy, I'd like the worker to be busy.

Also, I've considered avoiding the queue altogether and simply letting tasks round-robin to all workers, but it's preferable to have a single waiting line as some tasks may be accomplished faster than others. Furthermore, I'd like insight into how many jobs are remaining (which I can get from the queue) and the ability to cancel all or particular jobs.

How can I implement this message queuing/work distribution pattern while avoiding a polling?

Edit: It appears I'm looking for the Message Dispatcher pattern -- how can I implement this using Spring/Spring Integration?

+2  A: 

Perhaps you should look at the ExecutorService classes from the concurrency package.

M. Jessup
and if you're interested in the threads handling the "work" to be cached, you can use `Executors.newCachedThreadPool()` although this is more of an implementation/tuning detail.
matt b
+2  A: 

In Spring Integration 2.0.0 we have added the <dispatcher/> subelement to the <channel/> element. You can use that to ensure asynchronous hand-off without using a poller.

This uses java.util.concurrent underneath.

<channel id="shareableWork">
    <dispatcher task-executor="pool"/>
</channel>
<thread-pool-task-executor id="pool" max-size="3"/>
iwein