java 为什么我必须在 try/catch 语句中包装每个 Thread.sleep() 调用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37594251/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why must I wrap every Thread.sleep() call in a try/catch statement?
提问by Sergio Gliesh
I am trying to write my first multi-threaded program in Java. I can't understand why we require this exception handling around the for loops. When I compile without the try/catch clauses it gives an InterruptedException. (Here is the message:
我正在尝试用 Java 编写我的第一个多线程程序。我不明白为什么我们需要围绕 for 循环进行这种异常处理。当我在没有 try/catch 子句的情况下进行编译时,它会给出一个InterruptedException。(这里是消息:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type InterruptedException
)
)
But when run with the try/catch, the sysout in the catch blocks are never displayed - implying no such exception was caught anyway!
但是当使用 try/catch 运行时,catch 块中的 sysout 永远不会显示 - 这意味着无论如何都没有捕获到这样的异常!
public class SecondThread implements Runnable{
Thread t;
SecondThread(){
t = new Thread(this, "Thread 2");
t.start();
}
public void run(){
try{
for(int i=5 ; i>0 ; i--){
System.out.println("thread 2: " + i);
Thread.sleep(1000);
}
}
catch(InterruptedException e){
System.out.println("thread 2 interrupted");
}
}
}
public class MainThread{
public static void main(String[] args){
new SecondThread();
try{
for(int i=5 ; i>0 ; i--){
System.out.println("main thread: " + i);
Thread.sleep(2000);
}
}
catch(InterruptedException e){
System.out.println("main thread interrupted");
}
}
}
回答by Nathan Hughes
The method Thread.sleep throws InterruptedException if it detects that the current thread has its interrupt flag set, waking up from its sleep early and allowing you to use the exception to relocate control to somewhere outside the current flow. That flag gets set only if something calls interrupt on the thread.
如果 Thread.sleep 方法检测到当前线程设置了中断标志,它会抛出 InterruptedException,提前从睡眠中唤醒并允许您使用异常将控制重新定位到当前流之外的某个地方。只有在线程上调用中断时才会设置该标志。
Since your program doesn't call interrupt on any of the threads, InterruptedException will not get thrown when you run this program. The compiler still requires you to catch the exception since it is a checked exception declared on the sleep method.
由于您的程序不会在任何线程上调用中断,因此运行此程序时不会抛出 InterruptedException。编译器仍然要求您捕获异常,因为它是在 sleep 方法上声明的已检查异常。
If you add a method like this to SecondThread
如果你将这样的方法添加到 SecondThread
public void cancel() {
t.interrupt();
}
then call cancel in the main method, like this:
然后在 main 方法中调用取消,如下所示:
public static void main(String[] args){
SecondThread secondThread = new SecondThread();
try{
for(int i=5 ; i>0 ; i--){
System.out.println("main thread: " + i);
Thread.sleep(2000);
secondThread.cancel();
}
}
catch(InterruptedException e){
System.out.println("main thread interrupted");
}
}
you'll see the println where the InterruptedException gets caught in SecondThread's run method.
您将看到在 SecondThread 的 run 方法中捕获 InterruptedException 的 println。
Compile errors show up in eclipse under the Problems tab, in addition to getting called out in the editor by getting underlined in red, they show up as you're editing the code. When you run this program any exceptions will get written to the console, along with the program output.
编译错误显示在 eclipse 中的问题选项卡下,除了在编辑器中通过以红色加下划线来调用之外,它们还会在您编辑代码时显示出来。当您运行此程序时,任何异常都会与程序输出一起写入控制台。
回答by Richard Tyregrim
InterruptedException is a checked exception and must be caught. In your code it is thrown by sleep-method. So if you do not wrap it or rethrow the compiler will halt, as it is a checked exception.
InterruptedException 是一个已检查的异常,必须被捕获。在您的代码中,它是由 sleep-method 抛出的。所以如果你不包装它或重新抛出编译器将停止,因为它是一个已检查的异常。
But in your example program, it will never get thrown in normal conditions as you do not interrupt. However, it is there to make sure that there is handling code for when a thread that is sleeping, waiting or is otherwise in a "zombie"-state has interrupt-flag set and thus is interrupted, either by code or by OS-level call.
但是在您的示例程序中,它在正常情况下永远不会被抛出,因为您不会中断。但是,它是为了确保当处于休眠、等待或处于“僵尸”状态的线程设置了中断标志并因此被代码或操作系统级别中断时,有处理代码称呼。
So it IS in fact needed to catch, and it has valid uses.
所以它实际上需要捕获,并且它有有效的用途。
回答by Oebele
When I compile without the try/catch clauses it gives an InterruptedException.
当我在没有 try/catch 子句的情况下进行编译时,它会给出一个 InterruptedException。
Exceptions are thrown at runtime, not while compiling, so this cannot be true!
异常是在运行时抛出的,而不是在编译时抛出,所以这不可能是真的!
Probably the compile error you were getting was that Thread.sleep
can throw InterruptedException
, but SecondThread.run
, from which Thread.sleep
is called, does not declare that it can throw it. Therefore the compiler fails, because the exception can't go anywhere.
您收到的编译错误可能是Thread.sleep
可以 throw InterruptedException
,但是SecondThread.run
从它Thread.sleep
被调用的 ,并没有声明它可以抛出它。因此编译器失败,因为异常不能去任何地方。
Normally there are two ways to solve this:
通常有两种方法可以解决这个问题:
- catch the exception, or
- add a
throws
clause to your method.
- 捕获异常,或
throws
在您的方法中添加一个子句。
The latter is not possible in this case, because SecondThread.run
overrides from Runnable.run
, which does not declare that it throws any exception. So you need to catch the exception.
在这种情况下,后者是不可能的,因为SecondThread.run
覆盖 from Runnable.run
,它没有声明它抛出任何异常。所以你需要捕获异常。
If this is not the case, or you meant "When running after compiling without the try/catch clauses it gives an InterruptedException.", please include the exact error message you got. Actually, you should always do that when asking questions here.
如果不是这种情况,或者您的意思是“在没有 try/catch 子句的情况下编译后运行时,它会给出 InterruptedException。”,请提供您得到的确切错误消息。实际上,在这里提问时您应该始终这样做。
回答by Andy Turner
You have to handle InterruptedException
in your threads because you're calling methods which throw InterruptedException
, and Java is designed so you always have to handle checked exceptions. That is is "in a thread" is irrelevant.
您必须InterruptedException
在线程中进行处理,因为您正在调用 throw 的方法InterruptedException
,而 Java 的设计使您始终必须处理已检查的异常。也就是说,“在一个线程中”是无关紧要的。
As it says in JLS Sec 11.2:
正如JLS Sec 11.2 中所说:
The Java programming language requires that a program contains handlers for checked exceptions which can result from execution of a method or constructor (§8.4.6, §8.8.5).
Java 编程语言要求程序包含检查异常的处理程序,这些异常可能由方法或构造函数的执行(第 8.4.6 节、第 8.8.5 节)产生。
These handlers can be in the form of try
/catch (InterruptedException)
, or throws InterruptedException
; however, you cannot use the latter because the method signature of void run()
doesn't allow you to add a checked exception.
这些处理程序可以采用try
/catch (InterruptedException)
或throws InterruptedException
; 但是,您不能使用后者,因为 的方法签名void run()
不允许您添加已检查的异常。
As such, you have to use try/catch.
因此,您必须使用 try/catch。