Java:从代码中调用可中断方法

Java:从代码中调用可中断方法,java,multithreading,concurrency,interrupted-exception,Java,Multithreading,Concurrency,Interrupted Exception,我正在阅读Java并发实践的第7章 在一节中,我们谈到了一些方法,这些方法本身没有取消策略,但是调用了可以中断的方法,这本书有以下几点要说 不支持取消但仍呼叫可中断的活动 阻塞方法必须在循环中调用它们,并在 检测到中断。在这种情况下,他们应该保存 本地中断状态,并在返回前将其恢复, 而不是立即捕捉到中断异常 我还没有完全理解这一点 这是否意味着,如果我在方法中调用Thread.sleep,我将不得不在循环中调用它 有人能解释一下为什么要这样做吗?据我所知:一个长时间运行的服务本身不能或不应该被中

我正在阅读Java并发实践的第7章

在一节中,我们谈到了一些方法,这些方法本身没有取消策略,但是调用了可以中断的方法,这本书有以下几点要说

不支持取消但仍呼叫可中断的活动 阻塞方法必须在循环中调用它们,并在 检测到中断。在这种情况下,他们应该保存 本地中断状态,并在返回前将其恢复, 而不是立即捕捉到中断异常

我还没有完全理解这一点

这是否意味着,如果我在方法中调用
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();
    }

  }