1

我正在开发一个需要一段时间(true)的系统,其中循环不断侦听队列并增加内存中的计数。

数据不断地进入队列,所以我无法避免 while(true) 条件。但自然它会将我的 CPU 利用率提高到 100%。

那么,我怎样才能让一个线程保持活动状态,它监听队列尾部并执行一些操作,但同时将 CPU 利用率降低到 100%?

4

6 回答 6

11

阻塞队列正是为此目的而发明的。

另请参阅:Java 中阻塞队列的优点是什么?

于 2013-02-08T00:02:51.893 回答
2

根据您对另一个答案的评论,您希望有一个基于 hsqldb 更改的队列

一些快速的谷歌搜索出现了:

http://hsqldb.org/doc/guide/triggers-chapt.html

看来您可以对其进行设置,以便更改导致发生触发器,该触发器将通知您编写的实现org.hsqldb.Trigger接口的类。让该类包含对LinkedBlockingDequeueJava 中 Concurrent 包中的 a 的引用,并让触发器将更改添加到队列中。

您现在有一个阻塞队列,您的读取线程将阻塞该队列,直到 hsqldb 触发触发器(来自写入器的更新),该触发器会将某些内容放入队列中。然后等待的线程将解除阻塞并将项目从队列中移出。

于 2013-02-08T00:29:06.783 回答
2

LinkedBlockingQueue.take() 是您应该使用的。这等待条目到达队列,不需要额外的同步机制。

(Java,IIRC 中还有一两个其他阻塞队列,但它们的特性使其不适用于一般情况。不知道为什么如此重要的机制在神秘的类中被埋得如此之深。)

于 2013-02-08T00:03:13.657 回答
2

通常,队列有办法从中检索项目,并且您的线程将被取消调度(因此使用 0% cpu),直到有东西到达队列...

于 2013-02-08T00:03:21.643 回答
1

lbalazscs 和 Brain 有很好的答案。我无法分享我的代码,他们很难为我的问题提供确切的解决方案。并且有一段时间(true)不断地轮询队列肯定是错误的方法。所以,这就是我所做的:

  1. 我使用ScheduledExecutorService了 10 秒的延迟。
  2. 我阅读了一组消息(比如 10k)并处理这些消息
  3. 再次调用线程并继续“循环”。

这大大减少了我的 CPU 使用率。欢迎提出建议。

于 2013-02-08T01:35:45.707 回答
-2

阅读书籍并且只在学校浪费时间的人提供了很多愚蠢的答案,而不是我看到的直接逻辑或答案。

while(true) 将设置您的程序以使用基本上由 Windows 算法“分配”给它的所有 CPU 能力来运行循环中的内容,通常一遍又一遍地尽可能快地运行。这并不意味着如果它在您的应用程序上显示 100%,如果您运行游戏,您的空循环 .exe 将占用您所有的操作系​​统 CPU 资源,游戏仍应按预期运行。它更像是一个视觉错误,类似于windows空闲进程和其他一些进程。解决方法是添加 Sleep(1)(至少 1 毫秒)或更好的 Sleep(5),以确保其他东西可以运行并确保 CPU 不会尽可能快地不断循环您的 while(true)。这通常会将视觉队列中的 CPU 使用率降至 0% 或 1%,因为 1 毫秒对于更老的 CPU 来说是一个很大的休息时间。

很多时候,while(trues) 或通用的无限循环是糟糕的设计,并且可以大大减慢到甚至 Sleep(1000) - 1 秒间隔检查或更高。无限循环并不总是糟糕的设计,但通常可以改进它们。

有趣的是,当我像 12 岁时学习 C 弹出并给出所有“愚蠢”的答案时,我学到了这个错误。

只要知道您是否尝试过,除非您学会使用的脚本化较慢的语言本身已将其固定在某个位置,否则当操作系统实际上有空闲资源时,Windows 会声称在执行空循环时会使用大量 CPU花费。

于 2019-07-27T20:21:53.300 回答