Object对象的wait、notify和notifyAll使用方法

it2025-02-16  4

Object对象的wait、notify和notifyAll使用方法 一.先说答案,再进行讲解二.正确示例三.错误示例1四.错误示例2

Object对象的wait、notify和notifyAll使用方法

Object的wait、notify 和 notifyAll是Object提供的同步方法,也就是所有对象都生而带来的方法,估计搞java的没有不知道这几个方法的。那么他究竟是怎么使用的呢?

一.先说答案,再进行讲解

wait() 与 notify()/notifyAll() 是Object类的方法,在执行两个方法时,要先获得锁。当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。当执行 notify()/notifyAll() 方法时,会唤醒一个处于等待该 对象锁 的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁。

注意: 从这里可以看出,notify()/notifyAll()执行后,并不立即释放锁,而是要等到执行完临界区中代码后,再释放。所以在实际编程中,我们应该尽量在线程调用 notify()/notifyAll() 后,立即退出临界区。即不要在 notify()/notifyAll() 后面再写一些耗时的代码。

二.正确示例

public class SynchronizedTest { public static void main(String[] args) throws Exception { Thread mt = new Thread(){ @Override public void run() { synchronized (this) { System.out.println("开始阻塞啦"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("阻塞结束啦"); } } }; mt.start(); Thread.sleep(500); synchronized (mt) { mt.notify(); } } }

运行结果:

开始阻塞啦 阻塞结束啦

上面的例子中,wait和notify方法都是在synchronized代码体中执行的,如果没有经过synchronized修饰,直接使用则会抛出java.lang.IllegalMonitorStateException异常。 至于原因,jdk源码wait方法中的描述为:

* The current thread must own this object's monitor. The thread * releases ownership of this monitor and waits until another thread * notifies threads waiting on this object's monitor to wake up * either through a call to the {@code notify} method or the * {@code notifyAll} method. The thread then waits until it can * re-obtain ownership of the monitor and resumes execution.

翻译过来:

当前线程必须拥有此对象监视器。该线程释放对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。

总结过来就是:要想使用wait等一系列方法,必须拥有当前对象的监视器(很多地方称为监视器锁)。

使用 synchronized 关键字,可以获取对象的监视器,对对象加锁

三.错误示例1

public class SynchronizedTest { public static void main(String[] args) throws Exception { Thread mt = new Thread(){ @Override public void run() { synchronized (this) { System.out.println("开始阻塞啦"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("阻塞结束啦"); } } }; mt.start(); Thread.sleep(500); // synchronized (mt) { mt.notify(); // } } }

执行结果:

开始阻塞啦 Exception in thread "main" java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at xxx

原因:

notify方法没有获得监视器。

四.错误示例2

public class SynchronizedTest { public static void main(String[] args) throws Exception { Thread mt = new Thread(new Runnable() { @Override public void run() { synchronized (this) { System.out.println("开始阻塞啦"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("阻塞结束啦"); } } }); mt.start(); Thread.sleep(500); synchronized (mt) { mt.notify(); } } }

执行结果:

开始阻塞啦 (线程持续wait中。。。

原因:

这个例子网上某个人写的错误写法,并不是wait和notify错误使用导致的问题,而是错误使用Runnable导致的,防止有人也会一时想不明白,也贴出来。

例子中使用 new Runnable 创建了一个匿名内部类并作为构造参数传给new Thread,导致构造的对象mt和匿名内部类的this不是同一个对象。所以导致notify不起作用= =、

引用: 1.https://www.cnblogs.com/dreamowneryong/p/11607742.html

最新回复(0)