Thread.sleep()与Thread.onSpinWait

时间:2018-07-06 17:34:07

标签: java

我有一个旋转等待循环,正忙于等待设置标志。但是,这可能需要很长时间(strong)-几分钟甚至几小时。

Thread.sleep()Thread.onSpinWait​()更有效率吗?

3 个答案:

答案 0 :(得分:6)

来自Thread#onSpinWait的{​​{3}}:

  

运行时可能会采取措施来改善调用自旋等待循环构造的性能。

Thread#sleep不会执行此操作,而是将处理器释放到另一个可运行线程,直到其睡眠时间结束。

如果我是您,我将重新设计您的系统,使其使用中断(事件)而不是轮询(繁忙等待),因为这将比Thread#sleepThread#onSpinWait带来更好的性能提升。

答案 1 :(得分:1)

在这种情况下,睡眠和自旋锁都不是您想要的。睡眠是错误的选择,因为您不知道需要多长时间才能入睡。进行某种自旋锁循环是错误的,因为自旋锁忙于等待,从而消耗了CPU周期,并且实际上仅意味着非常短的等待,以预期资源会很快变得可用。您要在此处设置信号灯。让线程1等待信号2设置信号量。

答案 2 :(得分:1)

因此,您想看看有关Object及其长期可用的wait()notify/All()方法的简短示例吗? (它们已经在20年前的there中的JLS 1.0中了)

不再说话:

public class NotifyTest {
  private boolean flag = false;
  public synchronized boolean getFlag() {
    return flag;
  }
  public synchronized void setFlag(boolean newFlag) {
    flag = newFlag;
    notifyAll();
  }

  public static void main(String[] args) throws Exception {
    final NotifyTest test = new NotifyTest();

    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.printf("I am thread at %,d, flag is %b\n",
                          System.currentTimeMillis(), test.getFlag());
        synchronized (test) {
          try {
            test.wait();
          } catch (InterruptedException ie) {
            ie.printStackTrace();
          }
        }
        System.out.printf("I am thread at %,d, flag is %b\n",
                          System.currentTimeMillis(), test.getFlag());
      }
    }).start();

    System.out.printf("I am main at %,d, flag is %b\n",
                      System.currentTimeMillis(), test.getFlag());
    Thread.sleep(2000);
    test.setFlag(true);
    System.out.printf("I am main at %,d, flag is %b\n",
                      System.currentTimeMillis(), test.getFlag());
  }
}

如果您的等待循环还有其他事情要做,Object.wait()也会有超时的变体。

因此可以wait()启用对象,然后可以通知等待线程(通过notify()的一个侍者或通过notifyAll()的所有侍者),甚至不必须彼此了解。
由于等待和通知都必须在同步块内进行,因此安全且有可能启动该块,检查变量/标志/任何内容并有条件地发出等待(只是此处未显示这些构造)。