0

I have 1000 big files to be processed in order as mentioned below:

  1. First those files needs to be copied to a different directory in parallel, I am planning to use ExecutorService with 10 threads to achieve it.
  2. As soon as any file is copied to another location(#1), I will submit that file for further processing to ExecutorService with 10 threads.
  3. And finally, another action needs to be performed on these files in parallel, like #2 gets input from #1, #3 gets input from #2.

Now, I can use CompletionService here, so I can process the thread results from #1 to #2 and #2 to #3 in the order they are getting completed. CompletableFuture says we can chain asynchronous tasks together which sounds like something I can use in this case.

I am not sure if I should implement my solution with CompletableFuture (since it is relatively new and ought to be better) or if CompletionService is sufficient? And why should I chose one over another in this case?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
user10916892
  • 825
  • 12
  • 33

1 Answers1

1

It would probably be best if you tried both approaches and then choose the one you are more comfortable with. Though it sounds like CompletableFutures are better suited for this task because they make chaining processing steps / stages really easy. For example in your case the code could look like this:

ExecutorService copyingExecutor = ...
// Not clear from the requirements, but let's assume you have
// a separate executor for this
ExecutorService processingExecutor = ...

public CompletableFuture<MyResult> process(Path file) {
    return CompletableFuture
        .supplyAsync(
            () -> {
                // Retrieve destination path where file should be copied to
                Path destination = ...
                try {
                    Files.copy(file, destination);
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
                return destination;
            },
            copyingExecutor
        )
        .thenApplyAsync(
            copiedFile -> {
                // Process the copied file
                ...
            },
            processingExecutor
        )
        // This separate stage does not make much sense, so unless you have
        // yet another executor for this or this stage is applied at a different
        // location in your code, it should probably be merged with the
        // previous stage
        .thenApply(
            previousResult -> {
                // Process the previous result
                ...
            }
        );
}
Marcono1234
  • 5,856
  • 1
  • 25
  • 43