That's the task and I'm asked to rework it to make use of a CountDownLatch
private final Object lock = new Object();
private volatile boolean isWaitingForValue = true;

CountDownLatch latch = new CountDownLatch(1);

public void someMethod() throws InterruptedException {
    synchronized (lock) {
        while (isWaitingForValue) {
            lock.wait();
        }

        retrieveValue();

        isWaitingForValue = false;
        lock.notify();
    }
}
But this code is stupid from the beginning. If I write test code (a main method), then to make the original code work I'd have to set the isWaitingForValue variable in the main (or some other task) to false and call notify on the lock object. In that case it's possible to pass the while condition and the wait. Still it is useless to set the var to false right after calling retrieveValue() as it is already false (to be able to pass the loop). If I rework the code now (and take the task requirements into account), then I'd have to write
public void someMethod() throws InterruptedException {
    latch.await();
    retrieveValue();
    latch.countDown();
}
And this is so pointless that I have no words for it. The latch has a counter set to 1. To pass the latch (as well as with the original code) I'll have to count down the latch in the main method or any other thread to zero... otherwise the latch can't be passed. So why would I have to countdown again when the latch is already zero? that's the requirements again: 3. The someMethod method must call the await method without parameters on the object stored in the latch field. 4. The someMethod method must call the retrieveValue method. 5. The someMethod method must call countDown on the object stored in the latch field. This way it would understand it.
public void someMethod() throws InterruptedException {
    latch.await();
    retrieveValue();
}

public static void main(String[] args) throws InterruptedException {

    Solution task = new Solution();

    // latch.countDown() in 2 secs
    new Thread(() -> {
        try {
            TimeUnit.SECONDS.sleep(2);
            task.latch.countDown();
        } catch (InterruptedException ie) { /* OK to interrupt this */ }
    }).start();

    // till the 2 secs aren't passed the main thread is waiting at the latch (latch.await())
    // probably better would be to use a CyclicBarrier as it is reusable
    task.someMethod();
}
Is there anyone out there who can shed light on this and tell me where I'm going wrong? Thank you, thank you, thank you so much.... 😜🤪🤩