限制运行Java中特定代码部分的线程数量的最佳方法?

问题描述 投票:0回答:2

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

我们正在研究类似于 Google Guava RateLimiter 的东西 - 但我们需要限制运行关键代码部分的线程数量,而不是限制每秒的调用次数。

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

java multithreading concurrency
2个回答
12
投票

这正是

java.util.concurrent.Semaphore
的设计目的。您可以像这样创建一个
Semaphore

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

然后对于关键区域你会做:

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

...就这么简单。


10
投票

虽然,

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
代替
Callable
,使用
invokeAll()
代替
execute
,等待任务完成、取消任务、返回任务值以及执行其他一些有用的操作。

Java 8 让它变得更简单,您可以使用 lambda 代替定义任务类:

executor.submit(() -> {
    // Do the work here
});
© www.soinside.com 2019 - 2024. All rights reserved.