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. 【转】arm 开发工具比较(ADS vs RealviewMDK vs RVDS)
  2. lua 学习 (一 )Mac搭建lua环境和ide
  3. 24Mybatis_延迟加载——用association来实现
  4. 记linux终端下怎样退出>
  5. Report_报表中Ref Cursor数据源的概念和用法(案例)
  6. Socket 之 API函数介绍
  7. Linux内核学习方法
  8. JPA---一对一关系
  9. 几个命令行命令的总结(node, babel-cli, babel-node)
  10. localstroge可以在页面间传递数值;
  11. 运用Unity实现AOP拦截器
  12. 【Python之路】第四篇--Python基础之函数
  13. 【转载】javadoc学习笔记和可能的注意细节
  14. 关于signal和fork的思考
  15. hibernate框架学习笔记3:API详解
  16. String 和 StringBuilder
  17. python程序如何脱离ide而在操作系统上执行
  18. anaconda2安装cv2
  19. 使用C#进行应用程序间通信(WPF与Unity通信)
  20. SPLAY,LCT学习笔记(一)

热门文章

  1. 2019牛客多校第八场 F题 Flowers 计算几何+线段树
  2. 什么是json? 什么是xml?JSON与XML的区别比较
  3. gulp常用插件之gulp-rev使用
  4. ROS学习--RViz使用的要点
  5. 1级搭建类107-Oracle 18c 单实例 FS(华为云)公开
  6. LVM实现将2块磁盘总空间“合二为一”并挂载到同一目录
  7. Hangfire设置隔天的指定时间执行
  8. Ueditor1.4.3.3 asp UTF-8版文件缺失修改方法
  9. vue koa2 mongodb 从零开始做个人博客(一) 登录注册功能前端部分
  10. AcWing 11. 背包问题求方案数