Object#wait()に関連するテスト

タイムアウト可能な同期をとって処理を行うメソッドを定義するとき、うっかり時間単位間違えて使ってエンバグすることがある.

private final Object mutex_ = new Object(); // モニタ
private String value_; // ガードする変数

public void method0(long timeout, TimeUnit unit) {
    long deadline = System.nanoTime() + unit.toNanos(timeout); // 単位はナノ秒固定
    synchronized (mutex_) {
        while (value_ == null) {
            long rest = deadline - System.nanoTime();
            if (rest <= 0) {
                break;
            }
            unit.timedWait(rest); // TimeUnit.NANOTIMES.timedWait(rest); が正解
        }
    }
}

待ちに関する処理を独立したメソッドにしておくとうっかり Object#wait() を使ってしまう. Object#wait()を使ってしまうと単位がミリ秒になるので、テストではTimeUnit.MILLISECONDS以外を使っておくとバグがあぶり出せて良い. 変数名に単位がナノ秒であることが分かるような名前を採用するのも良いかもしれない.