What do you think about the order preserving simplicity of Java?
List<Input> inputs = ...;
List<Output> results = inputs.parallelStream()
.map(this::processTask)
.collect(toList());
If you want more control or have more complex use cases, you can use an ExecutorService of your choice, handle the futures yourself or get creative with Javas new structured concurrency.