Is there a method in Java 8 to make a Thread sleep until an Instant using a specific Clock?
Asked Answered
F

3

12

Given a Clock, an Instant and the current Thread, is there already some (utility) method in the Java libraries that makes the current thread sleep until the given clock reaches the instant?

Something like

public static void sleepUntil(Instant instant, Clock clock) 
 throws InterruptedException;

?

I need this in a test setting where I am working with a custom slowed-down clock.

I know that it is easy to implement, but I would prefer a standard solution if available (but didn't find it so far).

Facia answered 30/9, 2015 at 15:43 Comment(10)
Actually, maybe not so easy to implement...Facia
Maybe you could somehow convert to TimeUnit and call its sleep?Track
No, because there seems to be no possibility to make TimeUnit aware of the custom clock.Facia
Unless you want to poll the Clock repeatedly, there isn’t even a hard way to implement what you want.Consolute
Yep, I think the only possibility to do it without frequent polling would be in the clocks implementation itself, making use of the knowldege about the respective clocks inner workings. Sadly, Clock doesn't define a suitable method, so let's wait for Java 12.Facia
Why not just wait on some object associated with the clock and have the clock notify items when it ticks over? If you're reimplementing cron with a custom time-keeper, you can still use wait-notify and have interested parties wait on different objects if they're interested in the next day tick versus the next second tick.Brash
Yes you could do that, but this would mean you have to extend Clock (standard clocks have no associated thread that could tick), use that custom clock everywhere, cast at many places, wrap the standard Clock implementations so that they extend the custom Clock class and so on. Maybe I'll do that, but its extremely ugly and a utility method is probably more pragmatic.Facia
@Holger: If the clock is slowed-down by a fixed amount, it may be possible. See below answer.Track
@user: sure, but that knowledge is already off-API.Consolute
In general, the operating system facilities that could provide this kind of functionality do not guarantee thread wake up at the precise instant, but rather guarantee wake-up at or after an instant.Homograph
T
2

First of all, Clock is a really simple class with little implementation and few uses in the standard API. SystemClock, OffsetClock and TickClock are examples in the same file. So the answer seems to be No, it is not in the default API.

If you are given the "slowed-down clock" and may not modify it to add the desired sleepUntil()-code, and it is slowed down by a fixed amount, you could do something like

public static void sleepUntil(Instant instant, Clock clock) 
    throws InterruptedException {

    Instant now = Instant.now(clock);
    long duration = now.until(instant, ChronoUnit.MILLIS);
    long testSleep
        = ( duration < 10000 )? (duration / 10) : 1000;
    long start = clock.millis();
    Thread.sleep(testSleep);
    long stop = clock.millis();
    double clockskew = (stop - start) / testSleep;

    now = Instant.now(clock);
    Thread.sleep(now.until(instant, ChronoUnit.MILLIS) * clockskew);
}

This first does a test run to determine the clock skew, then sleeps an adjusted duration.

(Maybe you need to adjust the instant in sleep to adjust to the other clock. Post your clock code if you wish to have it tested/adjusted.)

Track answered 3/10, 2015 at 9:38 Comment(0)
T
1

In my case, I was needed to wait for a particular time. My solution.

long expirationTime = System.currentTimeMillis() + 60_000;
Thread.sleep(expirationTime - System.currentTimeMillis());

Another way is to do it with do-while but actually, I couldn't see its advantages.

Tiepolo answered 29/9, 2019 at 14:39 Comment(0)
B
-2

The only way I can see to do that is to create a while loop and break from it when the clock has reached the given instant.

public static void sleepUntil(Instant instant, Clock clock) throws InterruptedException {
    while (clock.millis() < instant.toEpochMilli()) {
        Thread.sleep(1000);
    }
}

For fixed clock, this would loop forever though.

Bhatt answered 30/9, 2015 at 16:7 Comment(1)
That doesn't work, because Thread.sleep(long millis) uses the system clock and not the custom clock.Facia

© 2022 - 2024 — McMap. All rights reserved.