ExecutorServices and Guava
If you’ve written any kind of multi-threaded code with Java, you must know java.util.concurrent.Executors and java.util.concurrent.ExecutorService classes. An ExecutorService is an abstraction around threads that can be used to schedule and track the progress of asynchronous tasks. A nice thing about it is that you can write code that uses an ExecutorService and decide later which implementation you choose.
- Executors.newFixedThreadPool(N) creates an ExecutorService with a fixed N number of threads to run the tasks.
- Executors.newSingleThreadExecutor() will use a single thread to run the tasks.
- Executors.newCachedThreadPool() will reuse threads instead of creating a new one for each task. This is useful when you execute lots of short-lived tasks.
Java 8 adds new methods to Executors. One is Executors.newWorkStealingPool(). It creates a pool of “work-stealing” threads with a number of threads equals to the number of available processors on the machine. Useful for async tasks that spawn sub-tasks.
Guava also provides nice implementations or decorations of ExecutorService. You create them with MoreExecutors static factory class.
Let’s take a look at two methods that I like:
- MoreExecutors.getExitingExecutorService(ThreadPoolExecutor) converts a given ThreadPoolExecutor to an ExecutorService that exits when the application is complete. It will tweak the ThreadPoolExecutor to make it produce daemon threads. And it will register a ShutdownHook to wait for their completion. That’s something you don’t want to write yourself even if it’s not complicated. It’s useful if you want your application to end gracefully even if some ExecutorService was created somewhere.
- MoreExecutors.sameThreadExecutor() is a really nice trick to make some multi-thread code run synchronously. What it does it use the main thread, on which the tasks are scheduled, to run the tasks. A very effective way of testing multi-threaded code is to make it synchronous, MoreExecutors.sameThreadExecutor() is your friend!