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