在编写API时,我倾向于定义将超时参数作为参数的方法long timeout, TimeUnit unit.这遵循许多java.util.concurrent具有相同要求的方法.
在Java 8中,我注意到了包中的新Duration类java.time,并想知道我是否可以将新方法定义为具有Duration timeout参数.
我可以从中看到的优势是:
用户编写常量更容易:
private static final Duration ACQUIRE_TIMEOUT = Duration.ofMinutes(10);
someResource.acquire(ACQUIRE_TIMEOUT);
Run Code Online (Sandbox Code Playgroud)
VS
private static final long ACQUIRE_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(10);
someResource.acquire(ACQUIRE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
Run Code Online (Sandbox Code Playgroud)但这是一个可能的问题:
用户如何指定无限时间?
someResource.acquire(Long.MAX_VALUE, TimeUnit.MILLISECONDS); // No timeout
Run Code Online (Sandbox Code Playgroud)
VS
someResource.acquire(Duration.ofSeconds(Long.MAX_VALUE)); // Is this how it's done?
Run Code Online (Sandbox Code Playgroud)
哪里acquire(Duration)可以实现为:
public boolean acquire(Duration timeout) {
long millis;
try { millis = timeout.toMillis(); }
catch (ArithmeticException ignore) { millis = Long.MAX_VALUE; } // yuck!
...
}
Run Code Online (Sandbox Code Playgroud)
绝对不是最漂亮的代码.
有没有更好的方法呢?java.time.Duration在我提供的API中是否存在其他问题或原因我不应该用于超时参数?
你的代码
private static final long ACQUIRE_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(10);
someResource.acquire(ACQUIRE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
Run Code Online (Sandbox Code Playgroud)
抵消了在特定应用单元中与该单元一起提供价值的预期用途.预期用途应该是someResource.acquire(10, TimeUnit.MINUTES);
但它显示了这种方法的问题,因为不可能定义一个带有值和a的常量TimeUnit.所以Duration在这里有一点意义.
由于TimeUnit在大多数情况下是为并发API创建并由后端代码使用的众所周知的类型,我永远不会省略带(long,TimeUnit)签名的方法,但提供接受a的重载Duration并没有错.
当涉及到"无超时"问题时,大多数API都没有特殊处理Long.MAX_VALUE,无论它是以秒还是毫秒提供.观察到的"无超时"行为是由于这两个数量(Long.MAX_VALUE, TimeUnit.SECONDS)并且(Long.MAX_VALUE, TimeUnit.MILLISECONDS)表示时间这一事实,今天的计算机都无法存活.如果人类持续那么久,我们会很高兴.使用Long.MAX_VALUE-1将表现出相同的行为.
顺便说一下,一些并发工具无条件地在内部将超时转换为纳秒级,这意味着最大等待时间仅限于300年"仅",但我认为对于大多数仍然等于"几乎没有超时"的应用程序.
换句话说,在运行时操作中用作超时之间Duration.ofSeconds(Long.MAX_VALUE)和之间没有实际区别Long.MAX_VALUE, TimeUnit.MILLISECONDS.
附录:我首先忽略了关于实际实施的问题.我建议遵循上述转换为纳秒的行为,而不是使用毫秒.我能想到的最好的事情是
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);
}
Run Code Online (Sandbox Code Playgroud)
有可能用毫秒来做类似的事情,但是,我认为将来毫秒级的毫秒不精确度更可能成为问题,而最大超时限制在292年以上.
| 归档时间: |
|
| 查看次数: |
6631 次 |
| 最近记录: |