Java I/O超时的最佳异常类型是什么?
我编写了一个Java类,它实现了一个“锁文件”,以防止周期作业并发运行多次。它基于Java I/O超时的最佳异常类型是什么?,java,io,timeout,timeoutexception,lockfile,Java,Io,Timeout,Timeoutexception,Lockfile,我编写了一个Java类,它实现了一个“锁文件”,以防止周期作业并发运行多次。它基于java.nio.channels.FileChannel.tryLock并运行良好 我的类允许客户端代码提供一个超时值,指示它愿意等待锁文件变为可用的时间,如果出现超时,我将抛出一个IOException。这也很有效 但是我想知道是否有更好的异常类型可以使用,因为IOException是相当通用的。捕获IOException的客户端代码将无法知道问题是否由超时本身或文件系统的其他问题等引起(当然,除非其他问题抛出
java.nio.channels.FileChannel.tryLock
并运行良好
我的类允许客户端代码提供一个超时值,指示它愿意等待锁文件变为可用的时间,如果出现超时,我将抛出一个IOException
。这也很有效
但是我想知道是否有更好的异常类型可以使用,因为IOException
是相当通用的。捕获IOException
的客户端代码将无法知道问题是否由超时本身或文件系统的其他问题等引起(当然,除非其他问题抛出IOException
的子类)
简单浏览一下Java API,我看到了一些候选者,但出于各种原因,我并不真正喜欢其中任何一个:
java.util.concurrent.TimeoutException
(这不是真正的“并发”用法)java.nio.channels.FileLockInterruptionException
(文档指出了此异常的非常具体的原因;与我的情况不符)java.nio.channels.InterruptedByTimeoutException
(与上述原因类似)显然,自定义异常类是可能的,但我想知道标准API中是否有合适的内容。创建一个扩展IOException的自定义异常类。这允许客户端处理特定的异常(如果它愿意),或者作为一个通用的IOException以及所有其他可能失败的原因
易于实现。调用方易于使用。JDK包含许多超时异常的变体,如等,但不幸的是,没有父类,如
TimeoutException
,可以扩展或通常用于所有超时异常
因此,您可以编写一个自定义异常并使用它,如下所示:
public class FileTimeoutException extends IOException {
private String message;
public FileTimeoutException(String message) {
this.message= message;
}
//add the other required methods
}
我认为
java.util.concurrent.TimeoutException
是合适的。javadoc说:
“当阻止操作超时时引发异常。指定超时的阻止操作需要一种方法来指示超时已发生。”
您调用trylock的方法是作者设想的阻塞操作
你说:“这不是一个真正的“并发”用法”。。。但这取决于你的观点。您正在使用一个Lock
API,该接口在java.util.concurrent
包树中声明。假设您正在设计API,以便可以轻松地在并发应用程序中使用它。(如果没有……为什么没有?)
在我看来,使用
IOException
或IOException
的现有子类或自定义子类的唯一好理由是将客户机操作建模为I/O操作。例如,如果API使用I/O异常来通知其他事情
反对使用IOException
的另一个理由是它太笼统了。它表示API方法的调用方“您需要为任何IOException
做好准备”。这包括当前实现不会抛出的各种异常,但将来可能会抛出
另一种选择是声明自己的自定义异常类,该类不是
IOException
的子类。从表面上看,这似乎比I/O异常要好
至于“实现细节”问题,该类被设计并记录为使用磁盘上的文件作为锁定机制。所以,虽然这肯定是一个实现细节,但它是实现、接口等的定义。所以我认为IOException至少不是不合适的
我认为指定这样的API是个坏主意。假设您稍后决定另一种锁定可能更合适。如果在界面中指定了锁定详细信息,则无法更改它们。或者至少,如果不以可能破坏API现有客户端的方式“重写契约”,就不能这样做。您应该使用的任何东西都应该是
IOException
的子类型。我想说它几乎是在并发域中。您说:实现“锁定文件”以防止周期作业同时运行多次,然后你会说:这不是一个真正的“并发”用法。它是:一个线程持有锁,另一个线程试图获取锁。这绝对是一个并发问题。顺便说一句,您使用文件锁来处理这个并发问题的事实在我看来像是一个实现细节,所以我不会使用IOException。@jbnize我不是说“不并发”吗?因为java.util.concurrent API处理“java land”中的线程安全问题,我觉得这个用例超出了这个范围。我的锁文件还提供了跨进程边界的保护,因此我觉得它的作用域非常不同,使用Java并发包中的类可能会让人感到困惑。@jbnize至于“实现细节”问题,该类的设计和文档化是为了使用磁盘上的文件作为锁机制。因此,虽然这肯定是一个实现细节,但它是实现、接口等的定义。因此我认为IOException
至少不是不合适的。我不同意一些细节,但我喜欢理由。谢谢你的想法。我很可能会创建一个新的TimeoutException
子类,并抛出IOException
,因为这也可能发生,并且需要单独向调用者发送信号。