限制运行特定方法的线程数量的最佳方法是什么?

3

情况

  • 我有一个Web应用程序
  • 我有一个执行复杂数学运算的类
  • 方程式根据请求的不同而有时发生
  • 有时许多线程同时开始这个计算
  • 当太多计算开始时,电脑就会停止响应(完全冻结= 99 CPU使用率)

我的目标是

我的目标是避免停顿/冻结。

我猜测可以通过限制同时进行的计算数量来实现此目标(可能为NUMBER_OF_CPU_CORES-1)

问题是

如何最好地达到这个目标?

我知道有java.util.concurrent.Semaphore,但也许有更好的方法吗?


如果我的电脑只有一个核心,你就不会计算任何东西了吗? - Jeffrey
你能降低调用你方法的线程的优先级吗? - Martin James
@Jeffrey,当然是Math.min(1, NUMBER_OF_CPU_CORES - 1),只是不想关注这些细节。在生产环境中,这个Web应用程序将在至少有4个核心的服务器上执行,所以这不是问题。 - Sergey Karpushin
@MartinJames,是的,我相信我可以做到这一点。您的意思是不限制并发执行数量,只是降低这些线程的优先级? - Sergey Karpushin
4个回答

7

请查看Java ThreadPoolExecutor,它可以帮助您完成您想要做的事情。

希望这能有所帮助...


2
+1 - 这是最好的方法,因为它避免了编写大量低级同步代码。 - Stephen C
也许不总是最好的选择,但这绝对是一个很好的起点!+1 - user166390
1
我不需要控制这些线程。因为每个线程都是由Web应用程序容器创建的(每个请求在自己的线程中处理)。所以对于我来说,没有低级别的与线程相关的代码。 - Sergey Karpushin

2

您应该配置应用程序容器,限制您所需的请求数线程。

在没有这样做的情况下,Semaphore是完美的工具。使用 tryAcquire() 方法,并确保在 finally 块中放置相应的释放,如下所示:

if (permits.tryAcquire(7, TimeUnit.SECONDS)) 
  try {
    /* Do your computation. */
    compute();
  } finally {
    permits.release();
  }
else 
  /* Respond with "Too busy; try later," message. */

2

Semaphore(信号量)看起来正是你想要的。

你可能需要加入一些逻辑,以便使用Semaphore.tryAcquire(尝试获取许可)并在无法获取许可时向用户返回错误。如果使用阻塞的acquire(获取)方法,则仍会导致服务器被锁定。


0

降低调用您方法的线程的优先级。如果盒子上的其余应用程序不会占用CPU,这几乎不会影响您的计算,但按键等响应仍应良好。

实际上,我很惊讶即使有来自多个准备就绪的线程的CPU过载,(除非它们的优先级已被提高),盒子也会挂起/冻结。也许有些缓慢...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接