wait/notify 和 wait/interrupt 有什么区别?

What is the difference between wait/notify and wait/interrupt?

synchronized (Foo.class) {
    while (someCondition) {
        try {
            Foo.class.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();            
        }
    }
}

似乎当其他线程在该线程上调用 interrupt()notify() 时,该线程都会被唤醒。两者有什么区别吗?

--编辑--

我知道一个是通知对象,另一个是中断线程。但是这两种情况的结果都是一样的,就是这个线程被唤醒了,所以我想问的是这2种情况的结果有什么不同。

当一个线程在某个监视器上调用通知时,它会唤醒在该监视器上等待的单个线程,但是哪个 线程被唤醒是由调度程序决定的。 (或者一个线程可以调用notifyAll,它会唤醒所有等待那个monitor的线程,然后它们都去争夺这个monitor,然后失败的再回去等待。)所以调用的目标不一样,进行通知到监视器,它告诉调度程序选择一个线程来唤醒。

与通知不同,中断针对特定线程。并且中断不需要被中断的线程在监视器上等待。对于要在监视器上调用 wait 的线程,它必须先获取该监视器,然后等待释放该监视器,直到线程完成等待或被中断。

Oracle 的建议是仅在取消时使用中断。 java.util.concurrent 中的 类 也被设计为使用中断来取消。

在你的例子中,中断不会很有效,因为控制不会离开 while 循环,线程仍然必须检查它正在等待的条件,而 while 循环条件中没有检查是否中断标志被设置。被中断的线程很可能会立即返回等待状态。

为了让这段代码在被中断后退出,而不是return等待,在循环条件中添加中断标志状态的检查,并让 catch 块设置中断标志(抛出异常时重置):

synchronized (Foo.class) {
    while (someCondition && !Thread.currentThread().isInterrupted()) {
        try {
            Foo.class.wait();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();            
        }
    }
}
  1. Wait 方法用于挂起对象上的当前线程。 等待方法不是来自线程class而是来自java.lang.Object

  2. Notify方法用于唤醒等待对象的线程。 通知方法不是来自线程 class 而是来自 java.lang.Object.

  3. 中断方法用于表示当前线程是 应该停止当前作业执行并可以开始其他作业。 中断方法来自线程class.

让我们看看现实生活中的例子:

将电话视为对象,将人视为线程。 例如,假设 A 人正在使用电话,B 人也想使用电话,但 A 人即(线程 1)正忙于使用它,除非工作完成现在获取电话对象上的锁 B 即(线程 2)试图使用 Telephone 但由于 A 已获得 B 的锁,它进入等待状态直到锁被释放。

  • 如果 Telephone 对象调用 wait 方法,它将限制当前线程 要使用Telephone 会进入等待状态
  • 如果 Telephone 对象调用 notify 它将通知正在等待的线程 它获取锁并继续进行预期的工作。
  • 如果人员 A(线程 1)正在使用电话对象并且正在执行某些任务 但是中断方法被调用然后A将被告知停止 当前任务,可能需要执行分配的其他一些任务。

基本上,您不是在寻找教科书上的差异,而是在寻找它们的用例差异。

正如人们已经指出的那样,唤醒线程并不是唯一的结果,但是从线程 t2t1 调用 t1.interrupt() 将导致 InterruptedException线程 t1,这是 Object.notify()Thread.interrupt() 之间的一个很大区别。

你应该明白它的方法 Object.wait() 抛出检查 InterruptedException 并强制你处理它。 Object.wait

InterruptedException - if any thread interrupted the current thread before or while the current thread was waiting for a notification. The interrupted status of the current thread is cleared when this exception is thrown.

那么您应该参考 this question 以了解如何处理此异常。

两者之间的区别在于,一个用于通常的逻辑编程内容(等待和通知)的线程间通信,而另一个(中断)用于抢占式线程取消/终止,即使在阻塞操作的情况下也是如此。您必须注意 Java 不提供任何机制来抢先取消线程,因此您必须为此目的使用中断机制(显然,如果您需要的话。您很可能会忽略此异常,如果不适用于您的情况)。

Java 不会限制您在 InterruptedException 之后的操作,您可以做任何您想做的事情,但不建议将其用于实施线程取消策略以外的其他事情。当程序员编写多线程程序时,线程取消策略经常被忽略并且很少被讨论,这就是为什么您可能会发现很难理解用例的原因。

BlockingQueue.put(..)这样的API方法试图通过抛出InterruptedException来告诉你什么是即使它的阻塞操作也可以被抢先终止。不一定所有阻塞 API 方法都会为您提供该便利。

使用Thread.interrupt()的线程的

Cancellation/Termination不是强制的而是合作的机制,只是请求而不是命令。

强烈建议不要使用 e.printStackTrace();,因为如果打算将其记录为错误,这通常不是错误。

希望对您有所帮助!!