基础方法介绍
wait()
让当前线程进入等待(阻塞)状态,并释放当前线程所持有的锁。直到线程被唤醒
wait(long timeout)
当前线程进入等待(阻塞状态)直到被唤醒或超过指定的时间
wait(long timeout, int nanos)
当前线程进入等待(阻塞)状态,直到被唤醒或超过指定时间或被某个其他线程中断当前线程
notify()
唤醒某个此对象监视器上等待的线程
notifyAll()
唤醒此对象监视器上等待的所有线程
实例说明
wait方法释放锁
1)未使用wait方法
public class WaitAndNotifyTest {
public static void main(String[] args) throws InterruptedException {
Thread1 t1 = new Thread1("t1");
synchronized (t1) {
System.out.println(Thread.currentThread().getName() + " start t1");
t1.start();
System.out.println(Thread.currentThread().getName() + " continue");
}
}
}
class Thread1 extends Thread {
Thread1(String threadName) {
super(threadName);
}
@Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " start");
try {
sleep(3000);
System.out.println(Thread.currentThread().getName() + " end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
main start t1
main continue
t1 start
t1 end
2)使用wait方法
public class WaitAndNotifyTest {
public static void main(String[] args) throws InterruptedException {
Thread1 t1 = new Thread1("t1");
synchronized (t1) {
System.out.println(Thread.currentThread().getName() + " start t1");
t1.start();
/**
* 虽然t1.wait()是通过“线程t1”调用的wait()方法,
* 但是调用t1.wait()的地方是在“主线程main”中。而主线程必须是“当前线程”,
* 也就是运行状态,才可以执行t1.wait()。所以,此时的“当前线程”是“主线程main”!
* 因此,t1.wait()是让“主线程”等待,而不是“线程t1”!
*/
System.out.println(Thread.currentThread().getName() + " wait");
t1.wait();
System.out.println(Thread.currentThread().getName() + " continue");
}
}
}
class Thread1 extends Thread {
Thread1(String threadName) {
super(threadName);
}
/**
* 在此的示例中,去掉了notify()之后,程序确实也能正常执行。
* 那是因为"t1对象的同步锁"上只有两个线程:"主线程"和"t1线程"。"t1线程"执行完毕之后,没有其它线程再来和"主线
* 程"竞争这个同步锁了("主线程"也就没有继续等待的必要了)。于是,“主线程”就被唤醒从而继续执行了。
*
* 虽然去掉了notify(),程序也能正常执行;但是还是建议在程序中加上notify()。
*
* 补充说明一下"执行wait()进入等待状态的线程,有下面4种唤醒方式。"
* (01) 通过notify()唤醒
* (02) 通过notifyAll()唤醒
* (03) 通过interrupt()中断唤醒
* (04) 如果是通过调用wait(long timeout)进入等待状态的线程,当时间超时的时候,也会被唤醒。
*/
@Override
public void run() {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " start");
try {
System.out.println(Thread.currentThread().getName() + " notifty");
notify();
sleep(3000);
System.out.println(Thread.currentThread().getName() + " end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果:
main start t1
main wait
t1 start
t1 notifty
t1 end
main continue
由结果看出:
- 未使用wait方法时,主线程执行完毕后,新线程才开始执行;
- 使用wait方法后,在t1.wait时,主线程释放了其持有的t1对象同步锁,子线程获取到同步锁后开始执行,子线程运行完毕后主线程重新获取到锁后继续执行。