2012-01-09 320 views
19

我注意到NetBeans警告我在我的Java代码的while循环中使用Thread.sleep(),所以我对这个主题做了一些研究。看起来问题主要是表现问题,在计数器仍然处于睡眠状态时,您的条件可能会变为真,因此在等待下一次迭代时会浪费时间。这一切都非常有意义。while while循环中的Thread.sleep()

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

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

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

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

任何建议或意见将是最受欢迎的。

+0

我想在你的情况是完全正确的(如果你不能得到通知,当RPC调用完成)。解决警告的方法是在周期中使用do。 – kenota 2012-01-09 17:51:04

+2

我认为轮询RPC调用状态的成本需要相当高才能保证10秒钟的睡眠。一秒钟更合理,或根据先前的睡眠操作次数等待更长时间的睡眠(当然有一定的最大值)。 – 2012-01-09 19:48:28

+1

正如我所说的,远程操作运行几秒钟(我的意思是从3-5的任何地方)。鉴于一些边缘情况,有一种情况是10秒太短。 – 2012-01-10 12:57:25

回答

12

除非您的远程系统能够发出事件或以其他方式异步通知您,否则我认为上述内容完全不合理。您需要平衡您的sleep()时间与RPC调用的时间/负载之间的平衡,但我认为这是唯一的问题,并且上述内容似乎完全不受关注。

4

不能改变远端来提供一个“推送”通知,说明它是在其长时间运行的过程中完成的,这与你将能够做到的一样。只要Thread.sleep时间与轮询成本相比较长,您应该可以。

0

你应该(几乎)从不使用睡眠,因为它非常低效,而且它不是一个好习惯。总是使用线程互相发信号的锁和条件变量。见麦克道林的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(); 
    } 
    } 
} 
+3

我不太清楚这应该如何帮助。 – 2012-01-09 21:12:48

+0

嗯,我想他是问如何构建他的逻辑,我说(作为一般性评论),在while循环中,他应该使用一个条件变量来表示正在等待完成的过程,而不是连续使用睡觉。 – Cemre 2012-01-09 21:22:48

+2

我认为这忽略了RPC需要以某种方式进行轮询的实际问题,不是吗? – 2012-01-09 21:31:19