Java多线程在CPU负载方面的应用

9
我遇到了一个应用程序运行多个Java线程的问题。该应用程序运行多个工作线程,不断地查看输入队列,如果队列中有消息,则将其取出并处理。
在这些工作线程中,有另一个验证线程,定期执行检查以查看主机(应用程序运行的主机)是否仍然“良好”运行该应用程序。此线程更新一个AtomicBoolean值,工作线程在开始查看之前会验证它以查看主机是否OK。
我的问题是,在CPU负载高的情况下,负责验证的线程将花费更长的时间,因为它必须与所有其他线程竞争。如果在一定时间后AtomicBoolean没有被更新,则自动设置为false,给我带来了一个不好的瓶颈。
我的初始方法是提高验证线程的优先级,但深入挖掘后,我发现这不是一个可靠的行为,算法不应依赖于线程优先级来正确运行。
有没有其他的想法?谢谢!

通常情况下,优先级不应影响正常运行,但这似乎是一个调优问题。假设验证线程的 CPU 负载较低,而工作线程需要更多的 CPU,则给它们降低优先级。另外,请确保您的原子操作超时时间设置得不要过低。 - Ralf H
2
再一次:请展示您的“验证线程”的源代码。 - Andremoniy
5个回答

1

不要查看常规队列数据结构,使用java.util.concurrent包的LinkedBlockingQueue。

您可以运行一组线程池(可以使用执行器服务的固定线程池,即您选择的工作人员数量),然后执行LinkedBlockingQueue.take()。

如果消息到达队列,则将其提供给等待的线程之一(是的,take会阻塞线程,直到有东西可以提供为止)。

Linked Blocking Queue's take方法的Java API参考

希望对您有所帮助。


同意。不要让你的工作线程仅仅是旋转和窥视,当没有任务时,让它们wait()在锁上或者阻塞在队列上。很可能是你过于活跃的工作线程导致了响应迟钝。请正确地处理。 - Thomas W

0

更多的线程并不意味着更好的性能。通常情况下,如果您有双核处理器,2个线程可以获得最佳性能,3个或更多开始变得更糟。四核处理器应该最好处理4个线程,以此类推。因此,请注意使用多少线程。

在其他线程执行完它们的工作后,您可以将它们置于休眠状态,让其他线程继续执行它们的任务。我相信Thread.yield()会暂停当前线程,以便给其他线程留出时间。

如果您想让您的线程持续运行,我建议创建两个主线程,线程A和B。使用A作为验证线程,并从B中创建其他线程。因此,线程A获得更多的执行时间。


我认为默认情况下,线程会获得创建它的线程的优先级,因此在您描述的情况下,由线程B创建的线程将具有与线程A相同的优先级。如果我错了,请纠正我。 - Smith Cosmin
可能是这样,我不确定,但我的意思是你在线程A和B之间不断切换。B将需要运行多个线程,而A将是单个线程,因此A将获得更多的时间。所谓优先级,我并不是指线程优先级,而是指它将拥有更多的执行时间。让我更正一下,以使其更清晰明了。 - Steve

0

一种老派的限制工作速率的方法,完全不使用健康检查线程(因此绕过了这些问题),是在队列长度超过100时阻止或拒绝添加请求到队列中。这对于产生负载的客户端施加动态反压力,当工作线程超载时减缓它们的速度。

这种方法已经添加到Java 1.5库中,请参见java.util.concurrent.ArrayBlockingQueue。如果队列已满,则其put(o)方法会被阻塞。


很遗憾,我无法操作队列,因为它们处于限流范围内。 - Smith Cosmin

0
你是否正在使用Java并发包中的Executor框架?如果没有,可以试试。你可以尝试使用ScheduledExecutorService来进行验证线程。

我实际上正在使用ScheduledThreadPoolExecutor来进行验证线程。其他线程也是使用ScheduledThreadPoolExecutor创建的,但在不同的池中。这些线程执行的作业具有while循环,因此它们会持续执行。也许我漏掉了什么。 - Smith Cosmin

0

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