【问题标题】:How a sleeping thread can send interrupt to itself?睡眠线程如何向自己发送中断?
【发布时间】:2013-08-07 17:58:06
【问题描述】:

我正在阅读 Java 线程。我正在研究sleep() 方法。书中指出

当线程遇到sleep 调用时,它必须进入休眠状态 指定的时间量,除非它在唤醒之前被中断 时间。

我正在阅读有关中断的信息,但是线程如何向自身发送中断?我认同 另一个线程可以发送中断吗?我理解正确吗?此外,做这两个 将发送中断的线程应该具有相同的目标Runnable?如果 假设一个线程被中断,它会回到Runnable 状态吗?真的对不起, 如果我听起来很愚蠢,那对我来说只是很新鲜。谢谢

【问题讨论】:

  • 当你想学习多线程时,最好使用ExecutorServices,它们更容易使用,更健壮。我个人认为,使用普通线程有点过时了,并且使多线程变得比它需要的更复杂。
  • @Casey 即使在 Executor 框架内,理解中断过程也很重要。
  • @Casey,我对线程很陌生,所以首先要复习一下基础知识。
  • @assylias 在我看来,在被 ExecutorService 执行时使用 Thread.sleep 是一个严重的错误。您阻止整个线程并阻止其他作业被执行。这实际上可以控制整个 ExecutorService。如果您想在延迟后执行某些代码,则需要安排其他任务。 ExecutorServices 的一大优势是您不需要关心整个低级别的事情,例如睡眠/中断或等待/通知。

标签: java multithreading


【解决方案1】:

一个线程在睡眠时不能中断自己,因为它正在……睡眠。

一张图片值一千字,所以这里有一个简单的例子,一个线程开始休眠,主线程中断它:

public static void main(String[] args) throws Exception {
    Runnable sleeper = new Runnable() {
        public void run() {
            try {
                System.out.println("sleeper is going to sleep");
                Thread.sleep(1000);
                System.out.println("sleeper is awake");
            } catch (InterruptedException e) {
                System.out.println("sleeper got interrupted");
            }
        }
    };

    Thread t = new Thread(sleeper);
    t.start(); //run sleeper in its own thread
    Thread.sleep(500); //sleeping in main a little to make sure t is started
    t.interrupt();
}

哪个打印:

sleeper is going to sleep
sleeper got interrupted

【讨论】:

  • 我对你的例子有点困惑。在这里,您正在使可运行对象中的睡眠者进入 sleep()。然后,您再次在 main 方法中使当前线程进入 sleep()。在这种情况下,甚至 main 也可以休眠,因为它也可以是当前线程。然后你在 sleeper 实例本身上调用 interrupt() 。线程不能中断自己是不是有点矛盾。我确定,我以错误的方式感知示例,您能详细说明一下吗?
  • 睡眠者正在睡眠 10 秒,但是因为它在另一个线程中运行并且不需要立即创建这个线程,所以主线程将等待 500 毫秒(足够创建另一个线程的时间)之前打断睡眠者
  • 啊,我现在可以看到图片了。正确的。非常感谢。
  • @benz Runnable 只是一个任务容器,可以在未来由一个线程运行。声明 Runnable 不会运行它,因为您需要一个线程来运行它(在我的情况下为 t)。当您调用t.start 时,会发生两件事:创建一个能够与主线程并行运行的新线程,并且在该并行线程中执行sleeperrun 方法。然后主线程继续正常执行。所以当t.interrupt 被调用时,t 已经运行了大约 500 毫秒并且还在休眠中......
  • 这是否意味着线程可以中断自己?不能告诉另一个线程中断对吧?
【解决方案2】:

至于主要问题 - 睡眠线程不能因为它睡眠而中断自己,但是任何其他线程都可以尝试中断睡眠线程。 Here you have doc explaining threads and thread lifecycle.

【讨论】:

  • 谢谢@Antoniosss,我有点困惑,发送中断的线程,它应该也有相同的 Runnable 吗?
【解决方案3】:

是的,只有另一个线程可以向休眠线程发送中断。线程不可能向自己发送中断(简单地将其与现实生活进行对比,如果一个人正在睡觉,那么要唤醒他,我们需要其他人)。是的,在中断线程后返回Runnable 状态。

【讨论】:

  • 第二句话困扰我,它允许线程自己中断。从 Oracle 文档中切入中断线程“除非当前线程正在中断自身,这始终是允许的......”
【解决方案4】:

据我所知,它是另一个导致中断的线程。所以当一个线程调用 sleep 一定时间时,Java Runtime 会记录下来,当时间过去时,它会引起中断,唤醒正在休眠的线程。

【讨论】:

  • 第二个线程在编写代码时不应该关心你。因为这是运行代码本身的 JRE 线程。
【解决方案5】:

根据Thread#interrupt

线程可以自行中断。它总是有可能的。

例子是:

public static void main(String[] args) throws ParseException, InterruptedException {   
  Thread.currentThread().interrupt();
  try{
        Thread.currentThread().sleep(200);
  }catch(InterruptedException ie){
        System.out.println("Current thread is interrupted");
  }
}

调用中断从不抛出异常。它设置中断状态标志
当此线程在调用 wait()wait(long)wait(long, int) 方法时被阻塞对象类,或 join()join(long)join(long, int)sleep(long) ,或者sleep(long, int),这个类的方法,那么它的中断状态将被清除,它会收到一个InterruptedException。 或

【讨论】:

  • 睡觉的时候能不能打扰一下? :D
  • 线程可以中断自己,但不能在睡眠时中断。在您的示例中,线程从不休眠,因为当调用 sleep 时,它意识到它已被中断并立即引发异常。 sleep 也是一个静态方法,所以你可以使用 Thread.sleep。
  • @assylias 我同意你的看法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-24
  • 2011-05-14
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 2018-08-09
相关资源
最近更新 更多