Java:从代码中调用可中断方法
我正在阅读Java并发实践的第7章 在一节中,我们谈到了一些方法,这些方法本身没有取消策略,但是调用了可以中断的方法,这本书有以下几点要说 不支持取消但仍呼叫可中断的活动 阻塞方法必须在循环中调用它们,并在 检测到中断。在这种情况下,他们应该保存 本地中断状态,并在返回前将其恢复, 而不是立即捕捉到中断异常 我还没有完全理解这一点 这是否意味着,如果我在方法中调用Java:从代码中调用可中断方法,java,multithreading,concurrency,interrupted-exception,Java,Multithreading,Concurrency,Interrupted Exception,我正在阅读Java并发实践的第7章 在一节中,我们谈到了一些方法,这些方法本身没有取消策略,但是调用了可以中断的方法,这本书有以下几点要说 不支持取消但仍呼叫可中断的活动 阻塞方法必须在循环中调用它们,并在 检测到中断。在这种情况下,他们应该保存 本地中断状态,并在返回前将其恢复, 而不是立即捕捉到中断异常 我还没有完全理解这一点 这是否意味着,如果我在方法中调用Thread.sleep,我将不得不在循环中调用它 有人能解释一下为什么要这样做吗?据我所知:一个长时间运行的服务本身不能或不应该被中
Thread.sleep
,我将不得不在循环中调用它
有人能解释一下为什么要这样做吗?据我所知:一个长时间运行的服务本身不能或不应该被中断,正在调用其他可以被中断的方法。因此,这个长期运行的服务应该能够检测到这一点,并通过一个方法或标志来报告它。但是它应该能够再次尝试该操作,而不是仅仅抛出InterruptedException
要调用阻塞的方法,意味着当前执行被阻塞,并等待阻塞方法返回值。这可以在一个循环中完成。然后您就知道方法调用是否成功,或者调用的方法是否中断。我没有这本书。但据我所知,如果一个活动被中断(顺便说一句,睡眠不是一个中断信号。但是你可以通过中断信号从睡眠中唤醒一个线程),那么该活动需要保存它的当前动态数据(中断状态),以便恢复自身并从以前的状态恢复。比如,
//Let's say you have integer data named "a"...
a = 45646;
//Normally after interruption, and terminating the activity data a is currently
//referencing @memory will be released...
//If you want to continue using data in a you have to save it somewhere
// persistant(Let's say a file)
void onInterruptionDetected()
{
saveToSomeFile(a, "temp.txt");
}
//After re-execution of activity(Assuming we need a's previous data in order to
// continue...), we can recover a's data(which is 45646) in previous interruption...
void onResumeDetected()
{
a = loadFromFile("temp.txt")
}
希望这有帮助,我还很困,可能有错误:)
我调用Thread.sleep在我的方法中,我将不得不在循环中调用它还是什么
当当前线程(被另一个线程)中断时,Thread.sleep()
将抛出一个InterruptedException
。你可以选择如何应对。如果你想睡觉,不管是否有人试图打断你,那么是的,你必须围绕try-catch块建立某种循环。您可能应该使用时钟(例如,System.nanoTime()
)来检查在引发异常之前您已睡眠了多长时间,然后继续睡眠剩余时间等
请注意,只有当另一个线程通过调用
(当前)thread.interrupt()
中断当前线程时,才会引发中断异常。它本身不会发生,所以一般来说,你不需要围绕睡眠或类似的东西构建任何循环。通常,线程被中断只是因为一个很好的原因(例如应用程序关闭),所以您可能希望支持取消/中断,除非没有特殊原因不支持。“特殊原因”可能是,例如,写入I/O设备并尝试确保所有数据都将被写入,而不管是否尝试取消。首先进行一些解释:
线程的中断状态基本上是一个布尔标志,由interrupt()
设置为“true”。
使用Thread.currentThread().isInterrupted()
,可以读取该标志的当前状态
如果可中断操作(如Object.wait()
或Thread.sleep()
)找到中断标志集
它将抛出一个中断异常
,同时清除(设置为“false”)标志,该标志可能如下所示:
if ( Thread.interrupted() ) { throw new InterruptedException(); }
注意并记住Thread.interrupted()
隐式清除中断标志!
这意味着,在执行catch(InterruptedException ie){…}
时,
线程本身不知道它被中断了
也就是说,让我们看两个例子:
首先是一个支持取消的任务示例。
在这里,我们并不真正关心任务在中止之前进行了多远:
public void run() {
int x = 0;
try {
while (x < 10) {
Thread.sleep(1000); // Some interruptible operation
x++;
}
System.out.println("x = " + x);
} catch (InterruptedException ie) {
System.out.println("Interrupted: x = " + x);
// We know we've been interrupted.
// Let the caller know it, too:
Thread.currentThread().interrupt();
}
}
在这种情况下,我们甚至在中断异常之后继续处理,直到任务完成。
为了保持友好,如果我们检测到一个中断,我们将该条件存储在wastinterrupted
中,以便
在从方法返回之前正确设置中断标志
这就是我的意思
应在本地保存中断状态,并在返回之前将其恢复
它说“应该”,因为我们没有严格要求以这种方式处理中断-我们也可以忽略任何InterruptedException
完成我们的任务,然后回来。但是,这不是上面提到的良好做法,在某些情况下可能会造成麻烦。这里给出了一个合理的解释:
public void run() {
int x = 0;
boolean wasInterrupted = false; // <- This is the local variable to store the interruption status
while (x < 10) {
wasInterrupted = wasInterrupted || Thread.interrupted(); // not really needed in this case, but for the sake of completeness...
try {
Thread.sleep(1000); // <- Some interruptible operation
} catch (InterruptedException e) {
wasInterrupted = true;
}
x++;
}
System.out.println("x = " + x);
if ( wasInterrupted ) {
Thread.currentThread().interrupt();
}
}