Java- Using invokeAll to get future results in order but only for some threads

T T picture T T · Oct 28, 2012 · Viewed 7.3k times · Source

I...really don't know how to word the title better. But basically, what I have is a thread pool with all these threads busily working. I want them to report their results in the order that they were assigned, but at the same time, I want to work in batches. To illustrate, and example would be

ExecutorService exec = Executors.newFixedThreadPool(8);

class MyCallable implements Callable<byte[]> {
    private final int threadnumber;

    MyCallable(int threadnumber){
        this.threadnumber = threadnumber;
    }

    public byte[] call() {
        //does something
    }
}
List<Callable<byte[]>> callables = new ArrayList<Callable<byte[]>>();

for(int i=1; i<=20; i++) {
    callables.add(new MyCallable(i));
}
try {
    List<Future<byte[]>> results = exec.invokeAll(callables);
    for(Future<byte[]> result: results) {
            System.out.write(result.get(), 0, result.get().length);
    }

Basically, the pool thread has 8 threads and I end up having 20 tasks (these are just examples). The way this works now, if I understand correctly, is that it waits until ALL 20 tasks are done before outputting them in order (from 1 to 20). What this program is supposed to do is output a continuous stream of bytes (which were processed by threads, and since I need to keep the order intact, I used the future interface). While I don't mind waiting until all 20 tasks are done, is there anyway so that the threads simply output in order as they go.

If there's no way or I'm just completely misunderstanding how invokeAll works, clarification there is welcome too. Thanks a bunch in advance! Executors are a bit confusing since I only just learned about them.

Random addendum, am I even allowed to return a byte array from a callable?

Answer

Keppil picture Keppil · Oct 28, 2012

invokeAll() waits until all results are computed before it returns.

Use a loop and submit() them one by one instead, this method returns a Future with the pending result immediately:

...
for(int i=1; i<=20; i++) {
    results.add(exec.submit(new MyCallable(i))); 
}
try {
    for(Future<Integer> result: results) {
            System.out.write(result.get(), 0, result.get().length);
    }
}
...