1.首先我们来从概念上理解一下这两个方法:

(1)obj.wait(),当obj对象调用wait方法时,这个方法会让当前执行了这条语句的线程处于等待状态(或者说阻塞状态),并释放调用wait方法的对象的对象锁。

当线程执行了obj.wait()这个语句之后,这个线程处于等待状态,需要其它线程用同一个obj对象调用notify或notifyAll方法,才可能唤醒这个处于等待状态的的线程。

(2)obj.notify(), 调用这个方法,就是唤醒其它 在obj这对象锁上处于等待状态 的线程,被唤醒的线程 在得到对象锁后 就会继续执行。

概念上的文字晦涩、让人理解的不够清晰,

我们来看代码吧,

这个小程序的目的就是:启两个线程,并让这两个线程切换着执行,并按序打印ababababababababababab。

 package cn.javaBase.study_thread1;

 class MyRunnable implements Runnable{
private String name;
private Object obj; public MyRunnable(String n, Object o) {
this.name = n;
this.obj = o;
} @Override
public void run() {
synchronized (obj) {
while (true) {
System.out.println(name);
obj.notify(); //当a线程执行到这里时,它就会唤醒另一个在obj对象锁中 处于等待状态的线程
//(也就是另一个在obj对象锁中调用了obj.wait() 语句的线程)
//注意,这里它不是唤醒 所有等待线程 中的任意一个, 而是唤醒 在obj这个对象锁上处于等待状态的 线程
try {
obj.wait(); //当a线程执行到这里,它就会让 当前线程a处于等待状态,并释放obj这个对象。
System.out.println("当前线程,会阻塞在这里");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} } public class Thread5AB { public static void main(String[] args) throws InterruptedException {
//这个程序中 共同的锁对象
Object o = new Object(); MyRunnable r1 = new MyRunnable("a", o);
MyRunnable r2 = new MyRunnable("b", o); Thread th1 = new Thread(r1);
Thread th2 = new Thread(r2); th1.start();
Thread.sleep(500); //这个是保证打印a的线程先启动
th2.start(); }
}

为了描述方便, 假设 上面的th1 和th2 分别代表着a、b线程

对于这个程序,重点应该是理解39、40行,r1和r2构造时,会什么传递的是同一个Object 类型的o对象,

因为:当a线程执行到22行时,a线程就处于等待状态,这时候b线程执行,当b线程直线到18行时,b线程就可以唤醒阻塞在o对象锁上的线程,而此时a线程不就是那个阻塞在o对象锁上的线程吗,

所以等b线程执行到18行时,a线程就被唤醒(但是这个时候a线程还不能进入synchronized代码块,就是这个对象锁中,因为进入这个代码块,需要有obj这个对象,obj这个对象就像是进入这个代码块的钥匙),

接下来等到b线程执行到22行时,b线程就把obj这个对象释放了,自己进入等待状态,此时a线程已经处于唤醒了的状态,并可以得到obj这个对象,所以接下来a线程就可以继续执行synchronized代码块中的内容,

这就是a、b线程第一次切换执行的过程,后面就依次这样循环执行,

控制台就打印了我们想要的结果ababababab...

重要的问题是,你要知道obj.notify()执行时,唤醒的是那个处于等待的线程,它唤醒的是在obj这个对象锁上处于等待的线程。

不知道这样解释的是否还可以,本人也是最近稿明白,

1.Java多线程之wait和notify的更多相关文章

  1. java多线程之wait和notify协作,生产者和消费者

    这篇直接贴代码了 package cn.javaBase.study_thread1; class Source { public static int num = 0; //假设这是馒头的数量 } ...

  2. Java多线程之Wait()和Notify()

    1.Wait()和Notify.NotifyAll都是Object的方法 2.多线程的协作是通过控制同一个对象的Wait()和Notify()完成 3.当调用Wait()方法时,当前线程进入阻塞状态, ...

  3. Java多线程之wait、notify/notifyAll 详解,用wait 和notifyAll 以及synchronized实现阻塞队列,多线程拓展之ReentrantLock与Condition

    前言:这几天看了很多关于多线程的知识,分享一波.(但是目前接触的项目还未用到过,最多用过线程池,想看线程池 请看我之前的博客) 关于基本的理论等 参考如下: https://www.cnblogs.c ...

  4. java多线程之wait和notify

    多线程中的通信是非常重要的概念,线程直接实现通信就可以并发完成很多复杂工作. java在Object类中就设计了wait()和notify()两个方法,以解决这个问题. 1.释义: wait()方法将 ...

  5. java 多线程之synchronized wait/notify解决买票问题

    一.Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable):当调用线程对象的st ...

  6. JAVA多线程之wait/notify

    本文主要学习JAVA多线程中的 wait()方法 与 notify()/notifyAll()方法的用法. ①wait() 与 notify/notifyAll 方法必须在同步代码块中使用 ②wait ...

  7. JAVA多线程之volatile 与 synchronized 的比较

    一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空 ...

  8. java多线程之yield,join,wait,sleep的区别

    Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...

  9. Java多线程之ConcurrentSkipListMap深入分析(转)

    Java多线程之ConcurrentSkipListMap深入分析   一.前言 concurrentHashMap与ConcurrentSkipListMap性能测试 在4线程1.6万数据的条件下, ...

随机推荐

  1. USB闪存驱动器未显示在MacOS的Finder或磁盘工具上?为什么Mac无法识别USB该如何解决?

    您可能会在Mac上无法显示的闪存驱动器上形成困扰.您确定驱动器正常,但Mac计算机无法检测到.  阅读这篇文章,闪存驱动器未显示在MacOS的Finder或磁盘工具上?为什么Mac无法识别USB该如何 ...

  2. hextorgb

    function hexToRgb(hex) { // By Tim Down - http://stackoverflow.com/a/5624139/3493650 // Expand short ...

  3. Constructing Roads POJ - 2421 最小生成树板子题

    #include<iostream> #include<cstring> #include<algorithm> using namespace std; ; in ...

  4. 0级搭建类008-Ubuntu Server Linux安装 (18.04.2) 公开

    项目文档引子系列是根据项目原型,制作的测试实验文档,目的是为了提升项目过程中的实际动手能力,打造精品文档AskScuti. 项目文档引子系列目前不对外发布,仅作为博客记录.如学员在实际工作过程中需提前 ...

  5. 09 : 构造方法 & 代码块

    构造方法 概念 构造方法是一种特殊的方法,它是一个与类同名的方法 对象的创建就是通过构造方法来完成. 其功能主要是完成对象的创建或者对象的初始化 当类实例化new一个对象时会自动调用构造方法 构造方法 ...

  6. Python 高维数组“稀疏矩阵”scipy sparse学习笔记

    scipy 里面的sparse函数进行的矩阵存储 可以节省内存 主要是scipy包里面的 sparse 这里目前只用到两个 稀疏矩阵的读取 sparse.load() 转稀疏矩阵为普通矩阵 spars ...

  7. 机器学习作业(八)异常检测与推荐系统——Matlab实现

    题目下载[传送门] 第1题 简述:对于一组网络数据进行异常检测. 第1步:读取数据文件,使用高斯分布计算 μ 和 σ²: % The following command loads the datas ...

  8. Wannafly Camp 2020 Day 2F 采蘑菇的克拉莉丝 - 树链剖分

    如果暴力维护,每次询问时需要对所有孩子做计算 考虑通过树剖来平衡修改与询问的时间,询问时计算重链和父树,轻链的贡献预先维护好,修改时则需要修改可能影响的轻链贡献,因为某个点到根的路径上轻重交替只有 \ ...

  9. Wannafly Camp 2020 Day 2H 叁佰爱抠的序列 - 欧拉遍历

    转化为完全图的欧拉遍历 如果 n 是奇数,则欧拉遍历长度为 \(n(n-1)/2\) 条边 如果 n 是偶数,则欧拉遍历长度为 \(n*n/2-1\) 条边 (即将(n-1)/2对点配对,剩下的一对当 ...

  10. Feign 不能注入报错及接口参数问题

    无法实例 解决方案: @EnableFeignClients(basePackages = "com.test.test.service") 要指定路径, 如果有设置@Compon ...