什么时候调用Thread.currentThread()。interrupt()以及什么时候不调用?

goo*_*gle 7 java multithreading interrupt

建议在互联网上的多篇文章中不要吞咽InterruptedException。当我要重用同一个线程时,使用这样的线程池执行程序来执行此操作更有意义。

public static void main(String[] args) throws InterruptedException {

    ExecutorService executor = Executors.newSingleThreadExecutor();
    Future<?> future = executor.submit(() -> {
        printNumbers(); // first call
        printNumbers(); // second call
    });
    Thread.sleep(3_000);                                     
    executor.shutdownNow();  // will interrupt the task
    executor.awaitTermination(3, TimeUnit.SECONDS);
}

private static void printNumbers() {
    for (int i = 0; i < 10; i++) {
        System.out.print(i);
        try {
            Thread.sleep(1_000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // preserve interruption status
            break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

上面来自DZone的代码示例。

但是在每次创建新线程的情况下:

Object LOCK = new Object();

public void doSomeJob() {

    myThread = new Thread(new Runnable() {
        public void run() {
            try {
               synchronized(LOCK) {
               System.out.println("Inside run");
               LOCK.wait();
              }
            } catch(InterruptedException ignored){}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还需要打电话Thread.currentThread().interrupt();吗?这有意义吗?

好的参考文献:

https://codepumpkin.com/interrupt-interrupted-isinterrupted-java-multithreading/

http://michaelscharf.blogspot.com/2006/09/dont-swallow-interruptedexception-call.html

mic*_*alk 8

我将根据Brian Goetz 的好书Concurrency in Practice的第7.1.2节给出答案。

在您的第一个示例中,您使用ExecutorService. ExecutorService管理它自己的线程。您不是这些线程的所有者,因此您不知道中断对它们意味着什么(例如ThreadPool可能会选择杀死被中断的线程并创建新线程)。这就是为什么在向此池提交可取消任务时应保留中断状态的原因。此引文适用于这种情况:

任务不在它们拥有的线程中执行。它们借用服务拥有的线程,例如线程池。不拥有线程的代码(对于线程池,线程池实现之外的任何代码)应该小心保留中断状态,以便拥有代码最终可以对其进行操作,即使“来宾”代码操作关于中断也是如此。(如果你是为某人看家,你不会在他们不在的时候扔掉邮件——你保存它并让他们在他们回来时处理它,即使你确实阅读了他们的杂志。)

在第二种情况下,您手动管理Thread的实例。所以你是它的所有者。因此,您决定中断对该线程意味着什么,并且如果您不想为其应用任何线程中断策略,则不必在第二种情况下保留中断状态

你不应该做的是InterruptedException通过捕捉它而不在 catch 块中做任何事情来吞下它,除非你的代码实际上是在为一个线程实现中断策略

另请注意,线程中断策略任务取消策略不同:

  1. 线程中断策略- 定义线程如何对中断做出反应(例如ThreadPool可能会杀死被中断的线程并创建一个新线程)。它由线程的所有者定义。
  2. 任务取消策略- 定义任务对取消的反应。取消通常是通过中断来实现的。执行任务的人选择是否响应中断任务。如果您的任务调用 throw 的方法,这很容易实现InterruptedException。或者您可以通过调用Thread::isInterrupted(例如在循环中)来检查线程的中断标志。任务的实现者选择如何处理这个问题。

此外,您不应该对线程中断策略进行任何假设(如果您不是 的所有者Thread)。这就是为什么保留中断状态或重新抛出InterruptedException被认为是一种很好的做法。

  • 这是正确答案!最好将其标记为正确答案 (3认同)

IQb*_*rod 3

如果您的锁来自java.util.concurrent.locks.Lock并且是可中断的(使用.lockInterruptibly()),那么中断进程确实有意义,因此一切都可能被中断和取消。
阅读文档Implementation Considerations中的章节。

但如果你的锁是non-interruptible(使用.lock()),那么它就没有意义,因为你将无法中断锁。

在您的情况下,您使用的是可中断的,如此wait()所写,并且会抛出一个.InterruptedException