目录
先上代码,注意看注释:
public class test {
private static Object lock = new Object();
static class ThreadA implements Runnable {
@Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
try {
System.out.println("ThreadA: " + i);
lock.notify();//通知之前持有 lock 锁并进⼊等待状态的线程B,说“线程B你不⽤等了,可以往下执⾏了”。
lock.wait();//然后释放自己的锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();//i++到底了for里面的lock.notify()就不会执行,这里补上
}
}
}
static class ThreadB implements Runnable {
@Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
try {
System.out.println("ThreadB: " + i);
lock.notify();//通知之前持有 lock 锁并进⼊等待状态的线程A,说“线程A你不⽤等了,可以往下执⾏了”。
lock.wait();//然后释放自己的锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock.notify();//i++到底了for里面的lock.notify()就不会执行,这里补上
}
}
}
public static void main(String[] args) throws InterruptedException {
new Thread(new ThreadA()).start();
Thread.sleep(1000);
new Thread(new ThreadB()).start();
}
}
执行结果:
关于第二notify()
在一个synchronized
代码块内部,如果没有获取到锁或者没有持有锁的情况下调用了notify()
或者wait()
方法,都会抛出IllegalMonitorStateException
异常。因此,确保在调用这些方法之前已经获取到锁,并且在调用这些方法后立即释放锁,是使用这些方法的正确方式。
在这个代码示例中,由于两个线程在synchronized
代码块内部交替执行,每次循环都会先执行notify()
唤醒另一个线程,再执行wait()
等待另一个线程的唤醒,因此不会抛出IllegalMonitorStateException
异常。但是,在其他情况下,如果没有正确地处理线程的等待和唤醒过程,就可能会出现线程阻塞或异常,从而导致程序出错。