NormalExecutorService4865447106310711038976137104163378132553196955489824610105761329674254896133105110752911167871022184410147885282715959248479622229673310496981056331010958Execution time :9410CompletionService1234567891012345678910123456789101234567891012345678109123456789101234567891012345678910123456789101235647891012345678910123456789101234568791012435687109Execution time :9405NormalLoop1234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910Execution time :28013

As you can see the total execution time between NormalExecutorService and CompletionService is the same, while the normal loop was more than 3 times slower. This is easily explained by the fact that the normal loop was single threaded and the others 2 were run with 3 threads.

The difference between NormalExecutorService and CompletionService is visible at runtime, NormalExecutorService always waits for the next thread to finish the job before printing the number, the client needs to wait until a big bunch of threads return all together.CompletionService is behaving differently, it follows a producer/consumer philosophy: as soon a thread is done, it puts the result into a non blocking queue so that the consumer can take it.

I hope this simple example will help you to better clarify the completion service as it did for me.