【问题标题】:Best way to limit number of threads running certain section of code in Java?限制在Java中运行某些代码部分的线程数的最佳方法?
【发布时间】:2016-07-24 12:00:49
【问题描述】:

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

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

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

【问题讨论】:

  • 为什么不能使用 java.util.concurrent.Semaphore?

标签: java multithreading concurrency


【解决方案1】:

这正是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();
}

...就这么简单。

【讨论】:

  • 我完全同意Semaphores,他们应该是这项任务的首选。不过,有一点值得一提:从技术上讲,一个线程可以进行多次获取。这意味着某些逻辑错误(例如,构思不当的递归)可能会导致线程未充分利用,甚至导致死锁。但如果小心使用,它们就是正确的工具。
  • 这段代码可能会产生一个错误:如果线程在等待 aquire() 方法时被中断,它将不会获得许可并释放一个额外的许可...
【解决方案2】:

不过,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
});

【讨论】:

  • 要记住的是,Executors 工厂构建了 ExecutorService 实现,这些实现由无限的作业队列支持。根据频率和运行作业需要多长时间,这可能会对系统产生负面影响。在某些情况下,由于内存中排队的作业数量,它可能会导致应用程序停止运行。在这些情况下,可能值得使用有界工作队列和自定义 RejectedExecutionHandler 创建自己的 ThreadPoolExecutor。看到代码部分的重要性,您可能想要无限制的版本。请注意影响。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
  • 2012-05-03
  • 2012-05-01
  • 1970-01-01
  • 2011-09-14
  • 2020-08-15
  • 1970-01-01
相关资源
最近更新 更多