Best way to limit number of threads running certain section of code in Java?
This is exactly what java.util.concurrent.Semaphore
was designed to do. You create a Semaphore
like so:
final int MAX_NOF_THREADS = 5;
final Semaphore mySemaphore = new Semaphore(MAX_NOF_THREADS);
then for the critical area you'd do:
try {
mySemaphore.aquire(); // This will hang until there is a vacancy
do_my_critical_stuff();
} finally {
mySemaphore.release();
}
... as simple as that.
Though, Semaphore
is the best choice here (look at the @Bex's answer) if you're careful, it's also possible to use ExecutorService
. Just wrap the piece of code you'd like to protect from unlimited concurrent access into a Callable
task and submit such tasks to the executor service:
// Task that will be executed
public class MyTask implements Callable<Void> {
@Override
public Void call() {
// Do the work here
return null;
}
}
// Service to execute tasks in no more than 5 parallel threads
// Cache it after creation and use when you need to execute a task
int maxThreadsCount = 5;
ExecutorService executor = Executors.newFixedThreadPool(maxThreadsCount);
// Execute a task. It will wait if all 5 threads are busy right now.
executor.submit(new MyTask());
With ExecutorService
you can also use Runnable
instead of Callable
, invokeAll()
instead of execute
, wait for task completion, cancel tasks, return values from them and do some other useful things.
Java 8 makes it simpler, you can use lambdas instead of defining task classes:
executor.submit(() -> {
// Do the work here
});