Thread.sleep() 在 while 循环中

Posted

技术标签:

【中文标题】Thread.sleep() 在 while 循环中【英文标题】:Thread.sleep() in a while loop 【发布时间】:2012-02-06 05:53:36 【问题描述】:

我注意到 NetBeans 警告我在我的 Java 代码中的 while 循环中使用 Thread.sleep(),所以我对这个主题进行了一些研究。似乎主要问题是性能之一,当计数器仍在休眠时,您的 while 条件可能变为真,因此在等待下一次迭代时浪费了挂钟时间。这一切都说得通。

我的应用程序需要联系远程系统并定期轮询操作的状态,等待操作完成后再发送下一个请求。目前代码在逻辑上是这样做的:

String state = get state via RPC call
while (!state.equals("complete")) 
    Thread.sleep(10000); // Wait 10 seconds
    state = update state via RPC call

鉴于情况是检查远程操作(这是一个有点昂贵的过程,因为它会运行几秒钟),这是在 while 循环中有效使用 Thread.sleep() 吗?有没有更好的方法来构建这个逻辑?我已经看到了一些可以使用 Timer 类的示例,但我看不到它的好处,因为它似乎仍然可以归结为上面相同的简单逻辑,但会带来更多的复杂性。

请记住,在这种情况下,远程系统既不在我的直接控制之下,也不是用 Java 编写的,因此在这种情况下将其更改为更加“合作”不是一种选择。我更新应用程序状态值的唯一选择是创建和发送 XML 消息,接收响应,解析它,然后提取我需要的信息。

欢迎任何建议或cmets。

【问题讨论】:

我认为在您的情况下这是完全正确的(如果您在 rpc 调用完成时无法收到通知)。绕过警告的方法是使用 do while 循环。 我认为轮询 RPC 调用状态的成本需要相当高才能保证 10 秒的睡眠。一秒钟会更合理,或者根据之前睡眠操作的数量(当然有一定的最大值)等待更长时间的睡眠。 正如我所指出的,远程操作会运行几秒钟(我的意思是从 3 到 5 秒)。考虑到一些极端情况,有一种情况是 10 秒太短了。 【参考方案1】:

除非您的远程系统可以发出事件或以其他方式异步通知您,否则我认为以上内容一点都不合理。您需要平衡您的 sleep() 时间与 RPC 调用所产生的时间/负载,但我认为这是唯一的问题,上述问题似乎根本不需要考虑。

【讨论】:

【参考方案2】:

如果无法更改远程端以提供“推送”通知,表明它已完成其长期运行的进程,那么您将能够做到这一点。只要 Thread.sleep 的时间比轮询的成本长,应该没问题。

【讨论】:

【参考方案3】:

您应该(几乎)永远不要使用睡眠,因为它非常低效且不是一个好习惯。始终在线程相互发出信号时使用锁和条件变量。请参阅 Mike Dahlin 的 Coding Standards for Programming with threads

模板是:

public class Foo
  private Lock lock;
  private Condition c1;
  private Condition c2;

  public Foo()
  
    lock = new SimpleLock();
    c1 = lock.newCondition();
    c2 = lock.newCondition();
    ...
  

  public void doIt()
  
    try
      lock.lock();
      ...
      while(...)
        c1.awaitUninterruptibly();
      
      ...
      c2.signal();
    
    finally
      lock.unlock();
    
  

【讨论】:

我不太确定这应该如何提供帮助。 嗯,我认为他在问如何构建他的逻辑,我说(作为一般性评论)在 while 循环内,他应该使用条件变量来由等待的进程发出信号完成而不是连续使用睡眠。 我认为这忽略了 RPC 需要以某种方式轮询的实际问题,不是吗? 最终“拥有”我需要检索的状态信息的远程组件不支持向我发出它已完成操作的信号。正如我所指出的,在这种情况下,更改远程端不是一种选择。

以上是关于Thread.sleep() 在 while 循环中的主要内容,如果未能解决你的问题,请参考以下文章

while 循环中的 Thread.sleep() 不能正常工作?

当我进行异步调用时,是不是有必要在 iOS 和 Android 的 while 循环中使用 Thread.Sleep(1)?

Java - 替代 thread.sleep

java中Thread.sleep(1000)问题

retry

Thread.sleep() 不工作。被跳过的操作