一、wait()
1、无参情况下:当前线程A释放对象锁,然后进入无限等待状态,直到被其他线程X 里object的notify()或者notifyAll()唤醒。
有参情况:wait(long timeoutMillis),参数为等待的最长时间。
当前线程A 释放对象锁,进入等待状态,当计时结束或其他线程X 里object的notify()或者notifyAll()唤醒。
2、由于执行wait()时必须释放对象锁,所以wait()必须处于synchronized(obj)下。
二、notify()
表示持有对象锁的线程A准备释放对象锁权限,通知jvm唤醒某个竞争该对象锁的线程X。
线程A synchronized 代码作用域结束后,线程X直接获得对象锁权限,其他竞争线程继续等待(即使线程X同步完毕,释放对象锁,其他竞争线程仍然等待,直至有新的notify ,notifyAll被调用,或者计时结束)。
三、notifyAll()
表示持有对象锁的线程A准备释放对象锁权限,通知jvm唤醒所有竞争该对象锁的线程,线程A 的synchronized 代码作用域结束后,jvm通过算法将对象锁权限指派给某个线程X,所有被唤醒的线程不再等待。
线程X synchronized 代码作用域结束后,之前所有被唤醒的线程都有可能获得该对象锁权限,这个由JVM算法决定。
四、联系
注意notify()和notifyAll()一般也要写在synchronized()里,并且锁对象要与wait() 的锁对象是同一个,因为需要避免唤醒不是正在等待的线程,请注意下面代码的第2行和29行
public class WaitingTest {
public static Object obj = new Object();//同一个静态对象
public static void main(String[] args) {
// 演示waiting
new Thread(new Runnable() {
@Override
public void run() {
while (true){
synchronized (obj){
try {
System.out.println( Thread.currentThread().getName() +"=== 获取到锁对象,调用wait方法,进入waiting状态,释放锁对象");
obj.wait(); //无限等待
//obj.wait(5000); //计时等待, 5秒 时间到,自动醒来
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( Thread.currentThread().getName() + "=== 从waiting状
态醒来,获取到锁对象,继续执行了");
}
}
}
},"等待线程").start();
new Thread(new Runnable() {
@Override
public void run() {
// while (true){ //每隔3秒 唤醒一次
try {
System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 等待3秒钟");
Thread.sleep(3000);//这里是为了保证jvm首先获取到的是上面的线程,避免时notify()没有正在等待的线程
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println( Thread.currentThread().getName() +"‐‐‐‐‐ 获取到锁对
象,调用notify方法,释放锁对象");
obj.notify();
}
}
// }
},"唤醒线程").start();
}
}