限制在Java中运行某些代码段的线程数的最佳方法是什么?

时间:2016-07-24 12:00:49

标签: java multithreading concurrency

我正在寻找一种限制线程数的方法,这些线程可以使用信号量或类似的方式在Java中运行某段代码。

我们正在寻找与Google Guava RateLimiter类似的东西 - 但不是每秒限制数量调用,我们需要限制运行关键代码段的线程数。

之所以需要这个,我们使用的某些库在这里存在问题,所以我们只是寻找一个快速的解决方法。

2 个答案:

答案 0 :(得分:6)

这正是java.util.concurrent.Semaphore的目的。您可以像这样创建Semaphore

final int MAX_NOF_THREADS = 5;
final Semaphore mySemaphore = new Semaphore(MAX_NOF_THREADS);

然后是你要做的关键领域:

try {
    mySemaphore.aquire(); // This will hang until there is a vacancy
    do_my_critical_stuff();
} finally {
    mySemaphore.release();
}

......就这么简单。

答案 1 :(得分:5)

尽管如此,Semaphore是最好的选择(看看@ Bex的答案),如果你小心,也可以使用ExecutorService。只需将您想要保护的代码包装成无限制的并发访问Callable任务,并将这些任务提交给执行程序服务:

// 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());

使用ExecutorService,您还可以使用Runnable代替CallableinvokeAll()代替execute,等待任务完成,取消任务,返回值他们并做一些其他有用的事情。

Java 8使其变得更简单,您可以使用lambdas而不是定义任务类:

executor.submit(() -> {
    // Do the work here
});