许多Java资源使用示例如下所示:
Resource r = openResource();
try {
// use resource
} finally {
r.close();
}
r
的声明必须在try
- 子句之外,才能在finally
- 子句中看到,但这也使得它看起来像是一种潜在的竞争条件: 如果在openResource()
- 调用和输入try
- 条款之间存在线程中断,该怎么办?
这是否意味着资源 实际上在那种情况下无法关闭?
或者Java保证try-finally
覆盖r
“完全”,尽管语法看起来不是这样吗?
或者我必须写:
Resource r = null;
try {
r = openResource();
// use resource
} finally {
if (r != null) r.close();
}
为了防止线程中断?
答案 0 :(得分:4)
这些Java资源使用示例可以像您在r
初始设置为null
时所提供的示例一样编写,但是如果它们使用Java 7 try-with-resources语法(假设{{1}实现AutoCloseable
):
Resource
然后它们将等同于第一个示例,其中try (Resource r = openResource()) {
// use resource
}
块之前调用openResource()
。 Java Language Specification for the try-with-resources
statement定义语义等同于在块之前使用初始化程序分配变量,然后输入try
块。
在输入try-catch-finally
块之前发生异常似乎存在问题。但问题在很大程度上是理论上的。如果try
正常返回并且在openResource()
的赋值和try块的开头之间没有介入语句,则不太可能,但不是不可能,其他一些线程在{ {1}}阻止开始,但即使这样,当你的线程再次开始运行时,它会毫无意外地进入r
块。如果另一个线程做了导致JVM关闭的事情,比如调用try
,那么通常不需要担心关闭资源。甚至这种情况也不大可能。
另一方面,如果打开资源时出现问题,可能会抛出try
,这会阻止System.exit
被分配。
答案 1 :(得分:4)
如果在openResource()之间存在线程中断 - 调用并输入try-clause会怎么样?
然后线程不会抛出InterruptedException
,直到它遇到一些阻塞调用。这在进入try
块之前不会发生,因为不再阻塞调用,假设方法实际返回。来自InterruptedException
的文档:
当线程正在等待,休眠或以其他方式占用时抛出,并且线程在活动之前或期间被中断。有时,方法可能希望测试当前线程是否已被中断,如果是,则立即抛出此异常。
请注意,即使你做将收购放在try
区块内,这也不能真正防止任何原本存在的竞争条件 - 因为你依赖于方法或构造函数首先返回。如果在方法/构造函数返回之后发生异常,那么为什么它不会在返回之前发生,但是在获取资源之后?如果发生这种情况,您无法在{... 1}上调用{<1}}。
我仍然建议在Java 7中使用try-with-resources语句,但是如果你看一下JLS section 14.20.3.1,你会发现扩展就像你的第一个一块代码:
基本的try-with-resources语句的含义:
close
通过以下转换给出局部变量声明和try-catch-finally语句:
try ({VariableModifier} R Identifier = Expression ...) Block
答案 2 :(得分:3)
没有潜在的竞争条件。您在调用getResource期间遇到异常,或者它可能返回null - 但是没有竞争条件。如果您的线程被中断,您可能会收到InterruptedException,但这会阻止您进入尝试块。
答案 3 :(得分:0)
阅读有关try-with-resources http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
的文章