如果我不是,谁在调用 Java Thread interrupt() 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2126997/
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
Who is calling the Java Thread interrupt() method if I'm not?
提问by SyntaxT3rr0r
I've read and re-read Java Concurrency in Practice, I've read several threads here on the subject, I've read the IBM article Dealing with InterruptedExceptionand yet there's something I'm simply not grasping which I think can be broken down into two questions:
我已经阅读并重新阅读了实践中的 Java 并发,我已经阅读了关于该主题的几个线程,我已经阅读了 IBM 文章处理 InterruptedException,但有些东西我根本没有掌握,我认为可以打破归结为两个问题:
If I'm never ever interrupting other threads myself, what can trigger an InterruptedException?
If I'm never ever interrupting other threads myself using interrupt()(say because I'm using other means to cancel my working threads, like poison pills and while (!cancelled)style loop [as both explained in JCIP]), what does an InterruptedExceptionthen mean? What am I supposed to do upon catching one? Shutdown my app?
如果我自己从不中断其他线程,什么会触发InterruptedException?
如果我自己从来没有使用interrupt()中断其他线程(比如说因为我使用其他方式来取消我的工作线程,比如毒丸和while (!cancelled)样式循环 [如 JCIP 中所解释的]),什么没有一个InterruptedException的则是什么意思?抓到一只我该怎么办?关闭我的应用程序?
采纳答案by Stephen C
The Thread interrupt mechanism is the preferred way to get a (cooperating) thread to respond a request to stop what it is doing. Any thread (including the thread itself I think) could call interrupt()
on a Thread.
线程中断机制是让(协作)线程响应请求以停止正在执行的操作的首选方式。任何线程(包括我认为的线程本身)都可以调用interrupt()
线程。
In practice, the normal use-cases for interrupt()
involve some kind of framework or manager telling some worker thread to stop what they are doing. If the worker thread is "interrupt aware" it will notice that it has been interrupted via an exception, or by periodically checking its interrupted flag. On noticing that it has been interrupted, a well-behaved thread would abandon what it is doing and end itself.
在实践中,通常的用例interrupt()
涉及某种框架或管理器,告诉某个工作线程停止他们正在做的事情。如果工作线程是“中断感知的”,它会注意到它已通过异常或通过定期检查其中断标志而被中断。在注意到它被中断时,一个表现良好的线程会放弃它正在做的事情并结束自己。
Assuming the above use-case, your code is likely to be interrupted if it is run within a Java framework or from some worker thread. And when it is interrupted, your code should abandon what it is doing and cause itself to end by the most appropriate means. Depending on how your code was called, this might be done by returning or by throwing some appropriate exception. But it probably should not call System.exit()
. (Your application does not necessarily know why it was interrupted, and it certainly does not know if there are other threads that need to be interrupted by the framework.)
假设上述用例,如果您的代码在 Java 框架内或从某个工作线程运行,则很可能会被中断。当它被中断时,你的代码应该放弃它正在做的事情,并以最合适的方式使自己结束。根据您的代码的调用方式,这可以通过返回或抛出一些适当的异常来完成。但它可能不应该调用System.exit()
. (您的应用程序不一定知道它为什么被中断,它当然也不知道是否有其他线程需要被框架中断。)
On the other hand, if your code is not designed to run under the control of some framework, you could argue that the InterruptedException
is an unexpected exception; i.e. a bug. In that case, you should treat the exception as you would other bugs; e.g. wrap it in an unchecked exception, and catch and log it at the same point you deal with other unexpected unchecked exceptions. (Alternatively, your application could simply ignore the interrupt and continue doing what it was doing.)
另一方面,如果您的代码不是为了在某个框架的控制下运行而设计的,您可能会认为这InterruptedException
是一个意外异常;即一个错误。在这种情况下,您应该像对待其他错误一样对待异常;例如,将它包装在一个未经检查的异常中,并在您处理其他意外的未经检查的异常的同一点捕获并记录它。(或者,您的应用程序可以简单地忽略中断并继续执行它正在执行的操作。)
1) If I'm never ever interrupting other threads myself, what can trigger an InterruptedException?
1) 如果我自己从不中断其他线程,什么会触发 InterruptedException?
One example is if your Runnable
objects are executed using an ExecutorService
and shutdownNow()
is called on the service. And in theory, any 3rd-party thread pool or thread management framework could legitimately do something like this.
一个例子是,如果您的Runnable
对象是使用ExecutorService
和shutdownNow()
在服务上调用的。理论上,任何 3rd 方线程池或线程管理框架都可以合法地做这样的事情。
2) If I'm never ever interrupting other threads myself using interrupt() ... what does an
InterruptedException
then mean? What am I supposed to do upon catching one? Shutdown my app?
2) 如果我从来没有使用interrupt() 自己中断过其他线程......
InterruptedException
那么是什么意思?抓到一只我该怎么办?关闭我的应用程序?
You need analyze the codebase to figure out what is making the interrupt()
calls and why. Once you have figured that out, you can work out what >>your<< part of the app needs to do.
您需要分析代码库以找出进行interrupt()
调用的原因以及原因。一旦你弄清楚了,你就可以计算出应用程序的 >>your<< 部分需要做什么。
Until you know why InterruptedException
is being thrown, I would advise treating it as a hard error; e.g. print a stacktrace to the log file and shut down the app. (Obviously, that's not always the right answer ... but the point is that this is "a bug", and it needs to be brought to the attention of the developer / maintainer.)
在你知道为什么InterruptedException
会被抛出之前,我建议把它当作一个硬错误;例如,将堆栈跟踪打印到日志文件并关闭应用程序。(显然,这并不总是正确的答案......但关键是这是一个“错误”,需要引起开发人员/维护人员的注意。)
3) How do I find out who / what is calling
interrupt()
?
3)我如何找出谁/什么在打电话
interrupt()
?
There is no good answer to this. The best I can suggest is to set a breakpoint on the Thread.interrupt()
and look at the call stack.
对此没有好的答案。我能建议的最好方法是在 上设置断点Thread.interrupt()
并查看调用堆栈。
回答by Brian Agnew
If you decide to integrate your code with other libraries, they can call interrupt()
on your code. e.g. if you decide in the future to execute your code within an ExecutorService, then that may force a shutdown via interrupt()
.
如果您决定将您的代码与其他库集成,他们可以调用interrupt()
您的代码。例如,如果您决定将来在ExecutorService 中执行您的代码,那么这可能会通过interrupt()
.
To put it briefly, I would consider not just where your code is running now, but in what context it may run in the future. e.g. are you going to put it in a library ? A container ? How will other people use it ? Are you going to reuse it ?
简而言之,我不仅会考虑您的代码现在在哪里运行,还会考虑它将来可能在什么上下文中运行。例如,你打算把它放在图书馆里吗?一个容器?其他人将如何使用它?你打算重复使用它吗?
回答by Ash
The InterruptedException
says that a routine maybe interrupted, but not necessarily that it will be.
该InterruptedException
说的例行可以被中断,但不一定,这将是。
If you don't expect the interrupt then you should treat it as you might any other unexpected exception. If it's in a critical section where an unexpected exception could have heinous consequences, it might be best to try and clean up resources and gracefully shutdown (because getting the interrupt signals that your well-engineered application that doesn't rely on interrupts is being used in a way it wasn't designed, and so there must be something wrong). Alternatively, if the code in question is something non-critical or trivial, you might want to ignore (or log) the interrupt and keep going.
如果您不希望中断,那么您应该像对待任何其他意外异常一样对待它。如果它处于关键部分,意外异常可能会产生令人发指的后果,最好尝试清理资源并正常关闭(因为获取中断信号,表明您的精心设计的应用程序不依赖于中断正在使用在某种程度上它不是设计的,所以一定有什么问题)。或者,如果有问题的代码不重要或无关紧要,您可能希望忽略(或记录)中断并继续执行。
回答by Tom Hawtin - tackline
The problem with the question is "I". "I" usually refers to a single instance of a class. I mean by that, that any particular piece of low-level code (class) should not rely upon the implementation of the entire system. Having said that you do have make some "architectural" decisions (like what platform to run on).
这个问题的问题是“我”。“I”通常指的是一个类的单个实例。我的意思是,任何特定的低级代码(类)都不应该依赖于整个系统的实现。话虽如此,您确实做出了一些“架构”决定(例如在什么平台上运行)。
Possible unexpected interrupts coming from the JRE are canceled tasks in java.util.concurrent
and shutting down applets.
来自 JRE 的可能意外中断是取消java.util.concurrent
小程序中的任务和关闭小程序。
Handling of thread interrupts is usually written incorrectly. Therefore, I suggest the architectural decision to avoid causing interrupts where possible. However, code handling interrupts should always be written correctly. Can't take interrupts out of the platform now.
线程中断的处理通常被错误地写入。因此,我建议架构决策尽可能避免引起中断。但是,处理中断的代码应该始终正确编写。现在不能从平台中取出中断。
回答by mangoDrunk
As already mentioned, another library can interrupt your threads. Even if the library doesn't have explicit access to the threads from your code, they can still get the list of threads that are running and interrupt them that way with the following method.
如前所述,另一个库可以中断您的线程。即使库没有从您的代码中显式访问线程,它们仍然可以获取正在运行的线程列表,并使用以下方法以这种方式中断它们。
回答by ?yvind Bakksj?
As others have pointed out, interrupting a thread (actually, interrupting a blocking call) is usually used for purposes of exiting cleanly or cancelling an ongoing activity.
正如其他人指出的那样,中断线程(实际上,中断阻塞调用)通常用于干净地退出或取消正在进行的活动。
However, you should not treat an InterruptedException
alone as a "quit command". Instead, you should think of interrupts as a means to control the running status of threads, much in the same way as Object.notify()
does. In the same way that you'd check the current state after waking up from a call to Object.wait()
(you don't assume that the wakeup means your wait condition has been satisfied), after being nudged with an interrupt you should check whyyou were interrupted. There is usually a way to do this. For example, java.util.concurrent.FutureTask
has an isCancelled()
method.
但是,您不应该InterruptedException
单独将 an视为“退出命令”。相反,您应该将中断视为控制线程运行状态的一种手段,与此类似Object.notify()
。与从呼叫唤醒后检查当前状态的方式相同Object.wait()
(您不认为唤醒意味着您的等待条件已满足),在被中断轻推后,您应该检查为什么被中断. 通常有一种方法可以做到这一点。例如,java.util.concurrent.FutureTask
有一个isCancelled()
方法。
Code sample:
代码示例:
public void run() {
....
try {
.... // Calls that may block.
} catch (InterruptedException e) {
if (!running) { // Add preferred synchronization here.
return; // Explicit flag says we should stop running.
}
// We were interrupted, but the flag says we're still running.
// It would be wrong to always exit here. The interrupt 'nudge'
// could mean something completely different. For example, it
// could be that the thread was blocking on a read from a particular
// file, and now we should read from a different file.
// Interrupt != quit (not necessarily).
}
....
}
public void stop() {
running = false; // Add preferred synchronization here.
myThread.interrupt();
}
回答by weekens
You could learn this by creating your own thread class (extending java.lang.Thread
) and overriding interrupt()
method, in which you record the stacktrace into, say, a String field, and then transfer to super.interrupt().
您可以通过创建自己的线程类(扩展java.lang.Thread
)和覆盖interrupt()
方法来学习这一点,在该方法中,您将堆栈跟踪记录到一个字符串字段中,然后转移到 super.interrupt()。
public class MyThread extends Thread {
public volatile String interruptStacktrace; // Temporary field for debugging purpose.
@Override
public void interrupt() {
interruptStacktrace = dumpStack(); // You implement it somehow...
super.interrupt();
}
}
回答by nawazish-stackoverflow
I think I understand why you are a bit confused about interruption. Please consider my answers in line:
我想我明白你为什么对中断有点困惑。请考虑我的回答:
If I'm never ever interrupting other threads myself, what can trigger an InterruptedException?
如果我自己从不中断其他线程,什么会触发InterruptedException?
Firstly you may interrupt other threads; I know that in JCiP it is mentioned that you should never interrupt threads you do not own; however, this statement has to be properly understood. What it means is that your code which might be running in any arbitrary thread should not handle interruption because since it is not the owner of the thread it has no clue of its interruption policy. So you may request interruption on other threads, but let its owner take the course of interruption action; it has the interruption policy encapsulated within it, not your task code; at least be courteous to set the interruption flag!
首先你可以中断其他线程;我知道在 JCiP 中提到你永远不应该中断你不拥有的线程;但是,必须正确理解此声明。这意味着您可能在任意线程中运行的代码不应处理中断,因为它不是线程的所有者,因此不知道其中断策略。所以你可以在其他线程上请求中断,但是让它的所有者来处理中断动作;它封装了中断策略,而不是你的任务代码;至少要有礼貌地设置中断标志!
There are many ways why there could be interruptions still, may be timeouts, JVM interrupts etc.
仍然存在中断的原因有很多,可能是超时、JVM 中断等。
If I'm never ever interrupting other threads myself using interrupt() (say because I'm using other means to cancel my working threads, like poison pills and while (!cancelled) style loop [as both explained in JCIP]), what does an InterruptedException then mean? What am I supposed to do upon catching one? Shutdown my app?
如果我自己从来没有使用 interrupt() 中断其他线程(比如说因为我使用其他方式来取消我的工作线程,比如毒丸和 while (!cancelled) 样式循环 [如 JCIP 中所解释的]),什么InterruptedException 是什么意思?抓到一只我该怎么办?关闭我的应用程序?
You need to be very careful here; if you own the thread which threw InterruptedException (IE), then you know what to do upon catching it, say you may shutdown your app/service or you may replace this killed thread with a new one! However, if you do not own the thread then upon catching IE either rethrow it higher up the call stack or after doing something (may be logging), reset the interrupted status so that the code which owns this thread, when control reaches it, may learn that the thread was interrupted and hence take actions as it will since only it knows the interruption policy.
在这里你需要非常小心;如果您拥有抛出 InterruptedException (IE) 的线程,那么您知道在捕获它时该怎么做,比如说您可以关闭您的应用程序/服务,或者您可以用一个新线程替换这个被杀死的线程!但是,如果您不拥有该线程,则在捕获 IE 时,要么将其重新抛出到调用堆栈的更高位置,要么在执行某些操作(可能正在记录)之后,重置中断状态,以便拥有该线程的代码在控制到达它时,可能了解到线程被中断,因此采取行动,因为只有它知道中断策略。
Hope this helped.
希望这有帮助。