监视器锁对象中的常用方法
1 wait()
1 该方法的是释放代用该方法的监视器锁同时该线程在此处被阻塞
2 阻塞后被唤醒的方式:
(1)其他线程中调用了该共享对象的notify()或者notifyAll()方法;
(2)其他线程调用了该线程的interrupt()方法,抛出InterruptException异常后返回
3 注意若线程持有多个监视器锁,只会释放调用了wait()方法的监视器锁对象
public class WaitTest01 {
public static Object resourceA = new Object();
public static Object resourceB = new Object();
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
try {
//获取A的锁
synchronized (resourceA) {
System.out.println("线程A获取到A资源的锁");
//获取B的锁
synchronized (resourceB) {
System.out.println("线程A获取到了B资源的锁");
//释放A锁
System.out.println("线程A释放了资源A的锁");
resourceA.wait();//线程A是放过了A资源锁,在此处阻塞,但并未释放B资源的锁,故线程B拿不到B资源锁
System.out.println("线程A阻塞");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread threadB = new Thread(() -> {
try {
Thread.sleep(1000);
//获取A的锁
synchronized (resourceA) {
System.out.println("线程B获取到A资源的锁");
System.out.println("线程B尝试获取资源B锁.....");
//获取B的锁
synchronized (resourceB) {
System.out.println("线程B获取到了线程B的锁");
//释放A锁
System.out.println("线程B释放了资源A的锁");
resourceA.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
threadA.start();
threadB.start();
System.out.println("main over");
}
}
最终输出结果:
main over
线程A获取到A资源的锁
线程A获取到了B资源的锁
线程A释放了资源A的锁
线程B获取到A资源的锁
线程B尝试获取资源B锁.....
补充:
1 wait(long timeout):线程调用该方法被挂起后,若在指定时限内未被唤醒回自己返回(wait()方法底层就是wait(0))
2 wait(long timeout, int nanos):底层调用的是wait(long timeout)
2 notify()/notifyAll
1 会唤醒调用该方法的共享对象中因调用该共享对象wait()方法而被挂起的一个线程
2 会唤醒调用该方法的共享对象中因调用该共享对象wait()方法而被挂起的所有线程
public class NotifyTest {
public static Object obj = new Object();
public static void main(String[] args) {
//创建线程A
Thread threadA = new Thread(() -> {
synchronized (obj) {
System.out.println("A线程执行了");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A线程被唤醒了");
}
});
//创建线程B
Thread threadB = new Thread(() -> {
synchronized (obj) {
try {
System.out.println("B线程执行了");
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("B线程被唤醒了");
}
});
//创建线程C用来唤醒线程
Thread threadC = new Thread(() -> {
synchronized (obj) {
System.out.println("线程C执行了");
obj.notify();
//obj.notifyAll();
}
});
//启动A和B
threadA.start();
threadB.start();
//唤醒其中的一个线程
try {
Thread.sleep(1000);
threadC.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
//等待两个线程结束
try {
threadA.join();
threadB.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main over");
}
}
3 注意事项
注意这些方法都是说共享对象的方法,就是说该线程必须持有该共享对象才能调用该方法,否则会抛出IllegalMonitorStateException异常