一:wait()函数
wait()是Object的里面的方法,Object是所有对象的父类,即所有对象都可以调用wait()方法。当一个线程调用一个共享变量的wait()方法时,该线程会被阻塞挂起。注意:如果调用wait()方法线程没有实现获取监视器锁,则调用wait()方法时会抛出IlleagalMonitorStateException异常
如下代码示例,线程A与线程B,在线程A中调用共享变量obj的wait()方法,在线程B中进行唤醒notify(),由于线程A,B没有获取到共享变量obj的监视器锁,故抛出lleagalMonitorStateException异常。
package org.binfa.concurrentprogramming.wait;
import lombok.extern.slf4j.Slf4j;
/**
* Object的Wati()方法
* @Author: jun
* @Date: 2022/7/17 21:00
*/
@Slf4j
public class WaitTest {
public static void main(String[] args) {
// 定义一个共享变量
Object obj = new Object();
// 创建线程A
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
log.info("线程" + Thread.currentThread().getName()+"开始执行");
try {
// 获取共享变量锁
synchronized(obj){
// 线程A 等待
log.info("线程" + Thread.currentThread().getName()+"等待");
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("线程" + Thread.currentThread().getName()+"执行结束");
}
},"A");
// 创建线程B
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
log.info("线程" + Thread.currentThread().getName()+"开始执行");
// 获取共享变量锁
synchronized (obj){
// 线程B 唤醒或者终端
log.info("线程" + Thread.currentThread().getName()+"唤醒");
obj.notify();
// threadA.interrupted();
}
log.info("线程" + Thread.currentThread().getName()+"执行结束");
}
},"B");
// 启动线程A
threadA.start();
try {
// 等待200ms,让线程B获取资源
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//启动线程B
threadB.start();
}
}
运行结果:
Exception in thread "A" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
线程A开始执行
at java.lang.Object.wait(Object.java:502)
at org.binfa.concurrentprogramming.wait.WaitTest$1.run(WaitTest.java:18)
at java.lang.Thread.run(Thread.java:748)
main线程:main
Exception in thread "B" java.lang.IllegalMonitorStateException
线程B开始执行
at java.lang.Object.notify(Native Method)
at org.binfa.concurrentprogramming.wait.WaitTest$2.run(WaitTest.java:31)
at java.lang.Thread.run(Thread.java:748)
添加synchronized(obj)监视器锁后
/**
* Object的Wati()方法
* @Author: jun
* @Date: 2022/7/17 21:00
*/
public class WaitTest {
public static void main(String[] args) {
// 定义一个共享变量
Object obj = new Object();
// 创建线程A
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程" + Thread.currentThread().getName()+"开始执行");
try {
// 获取共享变量锁
synchronized(obj){
// 线程A 等待
obj.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName()+"执行结束");
}
},"A");
// 创建线程B
Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程" + Thread.currentThread().getName()+"开始执行");
// 获取共享变量锁
synchronized (obj){
// 线程B 唤醒或者终端
// obj.notify();
threadA.interrupted();
}
System.out.println("线程" + Thread.currentThread().getName()+"执行结束");
}
},"B");
// 启动线程A
threadA.start();
try {
// 等待200ms,让线程B获取资源
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//启动线程B
threadB.start();
}
}
执行结果:
线程A开始执行
线程B开始执行
线程B执行结束
线程A执行结束
可以看到主程序线程A启动之后,休眠了200ms让出cup执行权,线程B开始执行后调用notify()方法对阻塞线程A进行唤醒。
故:当一个线程调用一个共享变量的wait()方法时,该调用线程会被阻塞挂起,直到发生下面几件事情之一才返回:(1)其他线程调用了该共享对象的notifyO或者notifyAll)方法;(2)其他线程调用了该线程的interruptO方法,该线程抛出InterruptedException异常返回。