synchronized (Foo.class) {
while (someCondition) {
try {
Foo.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
当这个线程上的某个其他线程调用interrupt()
或notify()
时,这个线程似乎都会唤醒。这两者之间有什么不同吗?
- 编辑 -
我知道一个用于通知一个对象,另一个用于中断一个线程。但是这两者都导致了相同的结果,也就是说,这个线程被唤醒了,所以我想问的是这两种情况是怎样的。后果各不相同。
答案 0 :(得分:3)
当线程在某个监视器上调用notify时,它会唤醒在该监视器上等待的单个线程,但哪个线程被唤醒由调度程序决定。 (或者一个线程可以调用notifyAll,唤醒等待该监视器的所有线程,然后它们都争用监视器,然后输入回到等待。)这就是呼叫目标不同的原因,通知发送到监视器,告诉调度程序选择要唤醒的线程。
与notify不同,中断以特定线程为目标。并且中断不要求被中断的线程在监视器上等待。对于要在监视器上调用wait的线程,它必须首先获取该监视器,然后等待监视的释放,直到线程完成等待或被中断。
Oracle的建议是仅使用中断进行取消。此外,java.util.concurrent中的类设计为使用中断进行取消。
在你的例子中,中断不会非常有效,因为控制不会离开while循环,线程仍然必须检查它等待的条件,以及那里的中断没有检查while循环条件是否设置了中断标志。被中断的线程可能会立即回到等待状态。
为了使该代码在被中断后退出,而不是返回等待,将中断标志状态的检查添加到循环条件,并使catch块设置中断标志(重置当抛出异常时):
synchronized (Foo.class) {
while (someCondition && !Thread.currentThread().isInterrupted()) {
try {
Foo.class.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
答案 1 :(得分:1)
基本上,您不是在寻找教科书差异,而是在使用案例上有所不同。
正如大家已经指出的那样,唤醒线程并不是唯一的结果,但是从t1.interrupt()
的线程t2
调用t1
将导致线程t1中出现InterruptedException
这是Object.notify()
和Thread.interrupt()
之间的巨大差异。
你应该理解它的方法Object.wait()
会抛出已检查InterruptedException
并迫使你处理它。 Object.wait。
InterruptedException - 如果有任何线程中断了当前线程 在当前线程等待通知之前或期间。该 此时清除当前线程的中断状态 抛出异常。
然后您应该咨询this question以了解处理此异常的想法。
两者之间的区别在于,一个用于通常逻辑编程内容(等待和通知)的线程间通信,而另一个(中断)用于抢占线程取消/终止,即使在阻塞操作的情况下也是如此。您必须注意,Java没有提供任何预先取消线程的机制,因此您必须为此目的使用中断机制(显然,如果您需要这样做。如果不适用,您可能会很好地忽略此异常在你的情况下)。
Java不会在InterruptedException
之后限制您的操作,您可以执行任何您想要的操作,但不建议将其用于实现线程取消策略之外的其他操作。当程序员编写多线程程序时,线程取消策略经常被忽略,讨论较少,这就是为什么你可能会发现很难理解用例的原因。
像BlockingQueue.put(..)这样的API方法试图通过抛出InterruptedException
告诉你的是,即使它的阻塞操作也可以被抢先终止。并非所有阻塞API方法都能为您提供这种功能。
取消/使用Thread.interrupt()
终止线程并不是一种强有力但合作的机制,而只是一个请求而非订单。
强烈建议不要使用e.printStackTrace();
,因为这通常不是错误,如果打算将其记录为错误。
希望它有所帮助!!
答案 2 :(得分:0)
Wait方法用于挂起对象上的当前线程。 Wait方法不是来自线程类,而是来自java.lang.Object
Notify方法用于唤醒等待对象的线程。 Notify方法不是来自线程类,而是来自java.lang.Object。
中断方法用于指示当前线程 应该停止当前的工作执行,并可以开始其他工作。 中断方法来自线程类。
让我们看看现实生活中的例子:
将电话视为对象,将人视为线程。 假设例如一个人正在使用电话而B人也想使用电话但是作为一个人即(线程1)正在忙着使用它,除非工作完成后获得电话上的锁定现在B即(线程2)试图使用电话,但是当A已获得锁定时,它进入等待状态直到锁定被释放。