java.util.concurrent.TimeUnit vs java.time.Duration for timeout arguments

You shouldn't be waiting for infinite time with a lock. There are other concurrency and inter thread signalling methods of locking and unlocking you should explore

java.time.Duration : Comes from Java 8 new Date and Time Api

java.util.concurrent.TimeUnit : Comes from Java concurrency package

If I am writing code associated with concurrency or Threads I would use TimeUnit but if I am writing code with manipulating Date, Time I am using Java 8 I would use java.time.Duration


Your code

private static final long ACQUIRE_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(10);
someResource.acquire(ACQUIRE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);

counteracts the intended use of providing a value in an application specific unit together with that unit. The intended use should be someResource.acquire(10, TimeUnit.MINUTES);

But it shows the problem with this approach as it is impossible to define a single constant bearing a value and a TimeUnit. So Duration has a point here.

Since TimeUnit is the well-known type created for concurrency APIs and used by the backend code in most cases, I would never omit the methods with the (long,TimeUnit) signature, but providing overloads accepting a Duration is not wrong.


When it comes to the “no timeout” question, most APIs don’t have a special treatment for Long.MAX_VALUE, regardless of whether it is provided as seconds or milliseconds. The observed “no timeout” behavior results from the fact that both quantities, (Long.MAX_VALUE, TimeUnit.SECONDS) and (Long.MAX_VALUE, TimeUnit.MILLISECONDS) denote a time, none of today’s computers will survive. We can be happy if mankind lasts that long. Using Long.MAX_VALUE-1 would exhibit the same behavior.

By the way, some concurrency tools unconditionally convert timeouts to the nanosecond scale internally, which implies that the maximum waiting time is limited to about 300 years “only”, but I assume that for most applications that still equals to “practically no timeout”.

In other words, there is no practical difference between Duration.ofSeconds(Long.MAX_VALUE) and Long.MAX_VALUE, TimeUnit.MILLISECONDS when used as a timeout in a runtime operation.


Addendum: I first overlooked your question regarding the practical implementation. I recommend to follow the behavior of converting to nanoseconds described above rather than using milliseconds. The best thing I can come up with is

public boolean acquire(long timeout, TimeUnit timeUnit) {
    // actual implementation
}
static final Duration MAX_WAIT = Duration.ofNanos(Long.MAX_VALUE);
public boolean acquire(Duration timeout) {
    return acquire(
        timeout.compareTo(MAX_WAIT)>=0? Long.MAX_VALUE: timeout.toNanos(),
        TimeUnit.NANOSECONDS);
}

It would be possible to do a similar thing with milliseconds, however, I think in the future the imprecision of milliseconds over nanoseconds is more likely to become an issue than the maximum timeout being limited to something above 292 years.

Tags:

Java

Java 8