【问题标题】:Java infinite loop performanceJava无限循环性能
【发布时间】:2015-08-29 16:08:33
【问题描述】:

我有一个线程,只有在特定情况下才能工作。否则它只会遍历一个空的无限循环:

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

【问题讨论】:

  • 使用BlockingQueue;这个无限循环会吃掉你所有的 CPU 时间。
  • 没有任何情况下该线程不起作用。它总是在工作。
  • 您的计算机有备用处理器吗?如果你有足够多的处理器,一个可连续运行的线程很便宜。如果没有,那就要花钱了。
  • 除了不必要地消耗 CPU 时间之外,您的第一个代码示例是不正确的:只有在某种同步操作在线程之间建立了先发生关系时,才能保证其他线程所做的更改是可见的。因此,您的代码可能无法检测到 ball 已设置。

标签: java multithreading performance infinite-loop


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    在您的线程之间共享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】:

      是的。这是busy waiting 最简单的实现,应尽可能避免。使用等待/通知或java.util.concurrent 机制。也许您应该更具体地了解您想要实现的目标以获得更有用的响应。

      【讨论】:

        【解决方案4】:

        您可能需要考虑让线程进入睡眠状态,并且仅在您的“球”变量变为真时才将其唤醒。有多种方法可以做到这一点,从使用非常低级别的waitnotify 语句到使用java.util.concurrent 类,它们提供了一种不太容易出错的方法。查看condition 接口的文档。像BlockingQueue 这样的数据结构也是一种解决方案。

        【讨论】:

          【解决方案5】:

          我发现了以下有趣的事情。在任务管理器中,像这样运行无限循环会消耗我 17% 的 CPU。现在,如果我添加一个简单的

          Thread.sleep(1)
          

          在只有一毫秒的循环内,CPU使用率几乎降到了零,就好像我没有使用程序一样,程序的平均响应时间仍然不错(在我的情况下它需要回复事情很快)

          【讨论】:

            猜你喜欢
            • 2010-12-29
            • 2016-05-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-04-25
            • 2012-01-24
            • 2013-04-06
            • 2011-01-06
            相关资源
            最近更新 更多