Java 多线程编程之:notify 和 wait 用法
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java 多线程编程之:notify 和 wait 用法,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3572字,纯文字阅读大概需要6分钟。
内容图文
wait 和 notify 简介
wait 和 notify 均为 Object 的方法:
- Object.wait() —— 暂停一个线程
- Object.notify() —— 唤醒一个线程
从以上的定义中,我们可以了解到以下事实:
- 想要使用这两个方法,我们需要先有一个对象 Object。
- 在多个线程之间,我们可以通过调用同一个对象的
wait()
和notify()
来实现不同的线程间的可见。
对象控制权(monitor)
在使用 wait 和 notify 之前,我们需要先了解对象的控制权(monitor)。在 Java 中任何一个时刻,对象的控制权只能被一个线程拥有。如何理解控制权呢?请先看下面的简单代码:
public class ThreadTest { public static void main(String[] args) { Object object = new Object(); new Thread(new Runnable() { @Override public void run() { try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }
直接执行,我们将会得到以下异常:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.xiangyu.demo.ThreadTest$1.run(ThreadTest.java:10) at java.lang.Thread.run(Thread.java:748)
出错的代码在:object.wait();
。这里我们需要了解以下事实:
- 无论是执行对象的 wait、notify 还是 notifyAll 方法,必须保证当前运行的线程取得了该对象的控制权(monitor)
- 如果在没有控制权的线程里执行对象的以上三种方法,就会报 java.lang.IllegalMonitorStateException 异常。
- JVM 基于多线程,默认情况下不能保证运行时线程的时序性
在上面的示例代码中,我们 new 了一个 Thread,但是对象 object 的控制权仍在主线程里。所以会报 java.lang.IllegalMonitorStateException 。
我们可以通过同步锁来获得对象控制权,例如:synchronized 代码块。对以上的示例代码做改造:
public class ThreadTest { public static void main(String[] args) { Object object = new Object(); new Thread(new Runnable() { @Override public void run() { synchronized (object){ // 修改处 try { object.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
再次执行,代码不再报错。
我们可以得到以下结论:
- 调用对象的
wait()
和notify()
方法,需要先取得对象的控制权 - 可以使用
synchronized (object)
来取得对于 object 对象的控制权
解题
了解了对象控制权之后,我们就可以正常地使用 notify 和 wait 了,下面给出我的解题方法,供参考。
public class ThreadTest { private final Object flag = new Object(); public static void main(String[] args) { ThreadTest threadTest = new ThreadTest(); ThreadA threadA = threadTest.new ThreadA(); threadA.start(); ThreadB threadB = threadTest.new ThreadB(); threadB.start(); } class ThreadA extends Thread { @Override public void run() { synchronized (flag) { for (int i = 0; i <= 100; i += 2) { flag.notify(); System.out.println(i); try { flag.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } class ThreadB extends Thread { @Override public void run() { synchronized (flag) { for (int i = 1; i < 100; i += 2) { flag.notify(); System.out.println(i); try { flag.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
发散:notify()
和notifyAll()
这两个方法均为 native 方法,在JDK 1.8 中的关于notify()
的JavaDoc如下:
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened.
译为:
唤醒此 object 控制权下的一个处于 wait 状态的线程。若有多个线程处于此 object 控制权下的 wait 状态,只有一个会被唤醒。
也就是说,如果有多个线程在 wait 状态,我们并不知道哪个线程会被唤醒。
在JDK 1.8 中的关于notifyAll()
的JavaDoc如下:
Wakes up all threads that are waiting on this object's monitor.
译为:
唤醒所有处于此 object 控制权下的 wait 状态的线程。
所以,我们需要根据实际的业务场景来考虑如何使用。
原文链接:https://segmentfault.com/a/1190000018096174?utm_source=tag-newest
参考地址:https://mp.weixin.qq.com/s/WoQtQSDygBwC_lJyOhf1EQ
内容总结
以上是互联网集市为您收集整理的Java 多线程编程之:notify 和 wait 用法全部内容,希望文章能够帮你解决Java 多线程编程之:notify 和 wait 用法所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。