睡眠并检查,直到情况属实

2022-09-01 14:05:30

Java中是否有一个库可以执行以下操作?应重复 a 持续 x 毫秒,直到条件变为真或达到最大时间。threadsleep

这种情况主要发生在测试等待某些条件变为真时。该病症受另一种 .thread

[编辑]为了更清楚起见,我希望测试在失败之前只等待X毫秒。它不能永远等待一个条件成为现实。我正在添加一个人为的例子。

class StateHolder{
    boolean active = false;
    StateHolder(){
        new Thread(new Runnable(){
            public void run(){
                active = true;
            }
        }, "State-Changer").start()
    }
    boolean isActive(){
        return active;
    }
}


class StateHolderTest{
    @Test
    public void shouldTurnActive(){
        StateHolder holder = new StateHolder();
        assertTrue(holder.isActive); // i want this call not to fail 
    }
}

答案 1

编辑

大多数答案都集中在具有等待和通知或条件的低级API上(其工作方式或多或少相同):当您不习惯它时,很难正确。证明:其中2个答案没有正确使用等待。
java.util.concurrent为您提供了一个高级API,其中隐藏了所有这些复杂性。

恕我直言,当并发包中有一个内置类实现相同的目标时,使用等待/通知模式是没有意义的。


初始计数为 1 的 CountDownLatch 正是这样做的:

  • 当条件变为 true 时,调用latch.countdown();
  • 在等待线程中,使用 :boolean ok = latch.await(1, TimeUnit.SECONDS);

人为示例:

final CountDownLatch done = new CountDownLatch(1);

new Thread(new Runnable() {

    @Override
    public void run() {
        longProcessing();
        done.countDown();
    }
}).start();

//in your waiting thread:
boolean processingCompleteWithin1Second = done.await(1, TimeUnit.SECONDS);

注意:倒计时闩锁是线程安全的。


答案 2

Awaitility提供了一个简单而干净的解决方案:

await().atMost(10, SECONDS).until(() -> condition());