The Executor Framework
It’s great. It allows you to handle concurrency in Java (or Groovy) without directly using the Thread class.
I first heard about the executor framework in Effective Java (Second Edition) (Item 68: Prefer executors and tasks to threads) and became really interested in it, decided to investigate further, and gave a presentation on it for my coworkers.
The Executors class (new in Java 5) provides a bunch of static factory methods for creating executors. With an executor, you can submit a task (Runnable or Callable) that will be performed by that executor. Here’s an example:
ExecutorService executor =
Executors.newSingleThreadExecutor();
executor.execute(runnable);
executor.shutdown();
As you can probably guess, this will create an executor which has a single thread. That thread will take the runnable and call its run() method. If the execute method is called multiple times, each runnable that’s passed in to the method will be placed on a queue. When the executor’s thread is available, it’ll pull the first runnable off the queue and run it. When that one finishes, it’ll grab the next one, and so on.
If a single thread isn’t enough, you can do the following:
ExecutorService executor = Executors.newFixedThreadPool(5);
for (Runnable runnable : runnables) {
executor.execute(runnable);
}
executor.shutdown();
This would create a thread pool with 5 threads that can execute the runnables. Again, the execute method places each of the runnables on a queue, and whenever one of the 5 threads is available, it pulls the runnable off the queue and runs it. That’s it! It’s so simple.
If you want to schedule your tasks to run at certain intervals, you can do this:
ScheduledExecutorService executor =
Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.MINUTES);
executor.shutdown();
This will submit a task to be executed every minute. The single thread in the executor will run the task right away, and then again every minute. The ’0′ above indicates the initialDelay – that is, the number of units to wait before the first invocation of the runnable. The ’1′ indicates the number of units between each invocation of the runnable. And, of course, TimeUnit.MINUTES indicates that the units for the ’0′ an ’1′ should be minutes.
If you’re using Groovy, it’s even easier because you don’t have to implement Runnable – you can just pass a closure to the executor (since Closure implements Runnable).
There’s no longer a reason to create threads directly in Java. The language now provides an easy way for you to run tasks in separate threads without having to micromanage them.
Now, we don’t have to worry about havoc which thread creates.
Any idea why the following is not supported?
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(callable, 0, 1, TimeUnit.MINUTES);
I have substituted runnable with callable in scheduleAtFixedRate method. It is not supported and you will get compiler error. Any idea?