views:

1450

answers:

5

Say I have a queue full of tasks which I need to submit to an executor service. I want them processed one at a time. The simplest way I can think of is to:

  1. Take a task from the queue
  2. Submit it to the executor
  3. Call .get on the returned Future and block until a result is available
  4. Take another task from the queue...

However, I am trying to avoid blocking completely. If I have 10,000 such queues, which need their tasks processed one at a time, I'll run out of stack space because most of them will be holding on to blocked threads.

What I would like is to submit a task and provide a call-back which is called when the task is complete. I'll use that call-back notification as a flag to send the next task. (functionaljava and jetlang apparently use such non-blocking algorithms, but I can't understand their code)

How can I do that using JDK's java.util.concurrent, short of writing my own executor service?

(the queue which feeds me these tasks may itself block, but that is an issue to be tackled later)

+1  A: 

Use a CountDownLatch.

It's from java.util.concurrent and it's exactly the way to wait for several threads to complete execution before continuing.

In order to achieve the callback effect you're looking after, that does require a little additional extra work. Namely, handling this by yourself in a separate thread which uses the CountDownLatch and does wait on it, then goes on about notifying whatever it is you need to notify. There is no native support for callback, or anything similar to that effect.


EDIT: now that I further understand your question, I think you are reaching too far, unnecessarily. If you take a regular SingleThreadExecutor, give it all the tasks, and it will do the queueing natively.

Yuval A
or just use Executors.newSingleThreadExecutor()
basszero
I just edited my answer :)
Yuval A
+8  A: 

Define a callback interface to receive whatever parameters you want to pass along in the completion notification. Then invoke it at the end of the task. You could even write a general wrapper for Runnable tasks, and submit these to ExecutorService.

class CallbackTask implements Runnable {

  private final Runnable task;

  private final Callback callback;

  CallbackTask(Runnable task, Callback callback) {
    this.task = task;
    this.callback = callback;
  }

  public void run() {
    task.run();
    callback.complete();
  }

}
erickson
Three answers in the blink of an eye! I like the CallbackTask, such a simple and straight forward solution. It looks obvious in retrospect. Thanks.Regarding others comments about SingleThreadedExecutor: I may have thousands of queues which may have thousands of tasks. Each of them need process their tasks one at a time, but different queues can operate in parallel. That's why I am using a single global threadpool. I'm new to executors so please tell me if I am mistaken.
Shahbaz
+1  A: 

If you want to make sure that no tasks will run at the same time then use a SingleThreadedExecutor. The tasks will be processed in the order the are submitted. You don't even need to hold the tasks, just submit them to the exec.

basszero
+4  A: 
Cem Catikkas
Don't you love SO's tag-stripping code? I never have figured out a good way to link to any method that takes more than one parameter.
Michael Myers
I'm just giving up... It's becoming more mess as I try to work around.
Cem Catikkas
Sometimes I just link to the class docs and say "Somewhere on this page...." :)
Michael Myers
<a href="...">method</a> with percent encoded (, ) and space worked fine ;-)
Peter Štibraný
@Peter: Well, at least it *looks* fine. But the anchor links don't work for me in IE7.
Michael Myers
Oh, it works fine in Firefox :-(
Peter Štibraný
Ah, wonderful!!!
Cem Catikkas
A: 

Or just use a fixed threadpool executor...