先来一张图简单理解一下

image.png 在Monitor对象中,主要包含Owner(存储的是当前持有这个锁的线程),EntryList(竞争锁时没有竞争到到进入EntryuList编程阻塞状态等待),WatiSet(存储的是曾经获得过CPU资源,就是Owner里面的线程对象,现在因为某种原因要放弃CPU资源进入WAITING状态,可被notify唤醒。)

1.Owner 线程发现条件不满足,调用 wait 方法,即可进入 WaitSet 变为 WAITING 状态 2.BLOCKED 和 WAITING 的线程都处于阻塞状态,不占用 CPU 时间片 3.BLOCKED 线程会在 Owner 线程释放锁时唤醒 4.WAITING 线程会在 Owner 线程调用 notify 或 notifyAll 时唤醒,但唤醒后并不意味者立刻获得锁,仍需进入EntryList 重新竞争

# 1.API介绍

  • obj.wait() 让进入 object 监视器的线程到 waitSet 等待--wait() 方法会释放对象的锁,进入 WaitSet 等待区,从而让其他线程就机会获取对象的锁。无限制等待,直到notify 为止。
  • wait(long n) 有时限的等待, 到 n 毫秒后结束等待,或是被 notify
  • obj.notify() 在 object 上正在 waitSet 等待的线程中挑一个唤醒(随机)
  • obj.notifyAll() 让 object 上正在 waitSet 等待的线程全部唤醒 这里强调一下,这几个都是Object对象的方法,且你只有获取到锁了才能调用这个方法(简单点来说,就是只能在同步代码块里调用)

# 2.sleep(long n) 和 wait(long n) 的区别

  • sleep 是 Thread 方法,而 wait 是 Object 的方法
  • sleep 不需要强制和 synchronized 配合使用,但 wait 需要和 synchronized 一起用
  • sleep 在睡眠的同时,不会释放对象锁的,但 wait 在等待的时候会释放对象锁
  • 4) 它们状态 TIMED_WAITING

# 3.Join原理

这快比较简单直接看下源码

image.png base就是获取当前系统时间, now就是一个中间变量,首先如果millis<0的话会抛出异常,如果millis==0的话就先通过isAlive方法判断一下当前线程是否存活,如果存活的话就调用wait(0)方法,就是一直等待下去,如果millis!=0,还是先判断线程是否存活,如果存活的话delay代表的是还需要等待的时间,如果还需要等待的时间小于0则退出循环代表不需要等待了,否则继续等待dealy时间,最后获取now就是获取当前系统时间和你刚开始进来时系统的时间,方便下次在循环里使用。这里涉及到一个模式叫做保护性暂停模式,有兴趣可以看下我下篇文章。