Java无限循环性能

9

我有一个线程,只有在特定情况下才需要工作。否则它会在一个空的无限循环中迭代:

public void run() {
    while(true) {
        if(ball != null) {
             // do some Calculations
        }
    }
}

循环实际上什么也不做,但每次迭代都必须检查是否需要进行计算,这会影响性能吗? 对我来说,仅在需要时创建线程不是一个选择,因为我的实现Runnable的类是一个可视化对象,必须始终显示。
编辑:那么以下解决方案好吗?还是使用其他方法更好(涉及性能)?
private final Object standBy = new Object();

public void run() {
    while(true) {
        synchronized (standBy) {
            while(ball != null)  // should I use while or if here?
                try{ standBy.wait() }
                catch (InterruptedException ie) {}
        }
        if(ball != null) {
             // do some Calculations
        }
}

public void handleCollision(Ball b) {
    // some more code..
    ball = b;
    synchronized (standBy) {
        standBy.notify();
    }
}

2
使用 BlockingQueue;这个无限循环会占用你所有的 CPU 时间。 - twentylemon
1
无论何时,此线程都在工作。它总是在执行任务。 - David Schwartz
1
你的电脑有多余的处理器吗?如果你有足够的处理器,一个持续运行的线程是很便宜的。如果没有,那就会花费你更多。 - Patricia Shanahan
参见:https://dev59.com/xGoy5IYBdhLWcg3wo_ro - assylias
除了不必要地浪费 CPU 时间之外,你的第一个代码示例是错误的:只有在某种同步操作建立线程之间的 happens-before 关系时,其他线程所做的更改才能保证可见。因此,你的代码可能无法检测到 ball 已被设置。 - meriton
5个回答

9
您可能需要考虑将线程休眠,只有当您的“ball”变量变为真时才唤醒它。有多种方法可以做到这一点,从使用非常低级别的waitnotify语句到使用提供更少错误的方式的java.util.concurrent类。请查看条件接口的文档。像BlockingQueue这样的数据结构也是一种解决方案。

8

是的,它可以。这是最简单的忙等待实现方式,应尽可能避免使用。使用wait/notify或java.util.concurrent机制。也许您应该更具体地说明您想要实现什么以获得更有用的响应。


3

在你的线程之间共享一个BlockingQueue

 class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

3

是的,这肯定会影响性能。为了提高性能,您可以考虑在代码中加入一些时间延迟(比如500毫秒或1000毫秒,甚至更长),具体取决于时间对您的重要性。


1
我发现了以下有趣的事情。在任务管理器中,运行那个无限循环会消耗我的CPU 17%的资源。现在,如果我添加一个简单的
Thread.sleep(1)

在循环内,只有一毫秒的时间,CPU 使用率几乎降至零,就好像我没有使用该程序一样,而且程序的响应时间仍然相当不错(在我的情况下需要快速回复)。

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