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();
}
}
}
Wait 方法用于挂起对象上的当前线程。
等待方法不是来自线程class而是来自java.lang.Object
Notify方法用于唤醒等待对象的线程。
通知方法不是来自线程 class 而是来自 java.lang.Object.
中断方法用于表示当前线程是
应该停止当前作业执行并可以开始其他作业。
中断方法来自线程class.
让我们看看现实生活中的例子:
将电话视为对象,将人视为线程。
例如,假设 A 人正在使用电话,B 人也想使用电话,但 A 人即(线程 1)正忙于使用它,除非工作完成现在获取电话对象上的锁 B 即(线程 2)试图使用 Telephone 但由于 A 已获得 B 的锁,它进入等待状态直到锁被释放。
- 如果 Telephone 对象调用 wait 方法,它将限制当前线程
要使用Telephone 会进入等待状态
- 如果 Telephone 对象调用 notify 它将通知正在等待的线程
它获取锁并继续进行预期的工作。
- 如果人员 A(线程 1)正在使用电话对象并且正在执行某些任务
但是中断方法被调用然后A将被告知停止
当前任务,可能需要执行分配的其他一些任务。
基本上,您不是在寻找教科书上的差异,而是在寻找它们的用例差异。
正如人们已经指出的那样,唤醒线程并不是唯一的结果,但是从线程 t2
为 t1
调用 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();
,因为如果打算将其记录为错误,这通常不是错误。
希望对您有所帮助!!
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();
}
}
}
Wait 方法用于挂起对象上的当前线程。 等待方法不是来自线程class而是来自java.lang.Object
Notify方法用于唤醒等待对象的线程。 通知方法不是来自线程 class 而是来自 java.lang.Object.
中断方法用于表示当前线程是 应该停止当前作业执行并可以开始其他作业。 中断方法来自线程class.
让我们看看现实生活中的例子:
将电话视为对象,将人视为线程。 例如,假设 A 人正在使用电话,B 人也想使用电话,但 A 人即(线程 1)正忙于使用它,除非工作完成现在获取电话对象上的锁 B 即(线程 2)试图使用 Telephone 但由于 A 已获得 B 的锁,它进入等待状态直到锁被释放。
- 如果 Telephone 对象调用 wait 方法,它将限制当前线程 要使用Telephone 会进入等待状态
- 如果 Telephone 对象调用 notify 它将通知正在等待的线程 它获取锁并继续进行预期的工作。
- 如果人员 A(线程 1)正在使用电话对象并且正在执行某些任务 但是中断方法被调用然后A将被告知停止 当前任务,可能需要执行分配的其他一些任务。
基本上,您不是在寻找教科书上的差异,而是在寻找它们的用例差异。
正如人们已经指出的那样,唤醒线程并不是唯一的结果,但是从线程 t2
为 t1
调用 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();
,因为如果打算将其记录为错误,这通常不是错误。
希望对您有所帮助!!