ExecutorService.invokeAll submits a collection of Callables and returns one Future per input after completion or a specified timeout, canceling unfinished tasks on return.
Java ExecutorService invokeAll: wait for a bounded batch with a deadline
Operational contract
This method limits the batch to 47 receipt tasks and waits up to three seconds. It keeps result positions aligned with task positions; cancelled tasks are reported as missing, while a task that failed raises ExecutionException to its caller. Timeout cancellation is an interrupt request, not proof that a blocked I/O operation stopped. The executor remains caller-owned and must be shut down by its owner. The deadline is for invokeAll, not for work done before constructing the task list.
Failure case
Forty-seven receipt checks are submitted. Three remain unfinished at the deadline and their futures are cancelled. Completed results retain input order even if task finish order differed.
Java code
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class ReceiptBatchDeadline {
public static List<String> collect(ExecutorService executor,
List<Callable<String>> lookups) throws InterruptedException, ExecutionException {
Objects.requireNonNull(executor);
Objects.requireNonNull(lookups);
if (lookups.size() > 47) throw new IllegalArgumentException("Batch exceeds 47");
List<Future<String>> results = executor.invokeAll(lookups, 3, TimeUnit.SECONDS);
List<String> receipts = new ArrayList<>(results.size());
for (Future<String> result : results) {
try { receipts.add(result.get()); }
catch (CancellationException timedOut) { receipts.add(null); }
}
return receipts;
}
}Performance and ownership cost
For N tasks, collecting futures and results costs O(N) application time and memory, with N capped at 47. Pool size and task duration determine execution time. The waiting phase is bounded by the invokeAll timeout, but cancellation cleanup may continue afterward.
Common Mistakes
- Do not assume returned futures are in completion order.
- Do not interpret cancel as guaranteed I/O termination.
- Do not submit an unbounded collection or forget who shuts down the executor.
