Java线程的等待通知是由wait()和notify()实现的。
关键点:
1.只能在同步方法块中调用wait()方法。
2.只有等通知的线程运行结束,被通知的线程才开始运行。
3.只能唤醒同一共享资源的线程,即只能notify相同对象的wait()方法。
下面是Demo:
SynchronizedDemo启动了三个线程,ThreadA和ThreadB两个是等待线程,ThreadC是通知线程。
ThreadC通知ThreadA和ThreadB停止等待继续执行。
package com.example.demo.synchronize;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SynchronizedDemo {
public static void main(String[] args) {
Object lock = new Object();
Thread threadA = new Thread(new ThreadA(lock));
Thread threadB = new Thread(new ThreadB(lock));
Thread threadC = new Thread(new ThreadC(lock));
threadA.start();
threadB.start();
threadC.start();
}
}
等待线程ThreadA:
package com.example.demo.synchronize;
import lombok.extern.slf4j.Slf4j;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadA implements Runnable {
private Object lock;
public ThreadA(Object obj) {
lock = obj;
}
@Override
public void run() {
log.info("begin---------");
try {
synchronized (lock) {
log.info("wait------");
lock.wait();
//通知线程结束后才开始唤起其它线程。
log.info("being notified------");
TimeUnit.SECONDS.sleep(new Random().nextInt(3));
}
}catch (Exception e){
e.printStackTrace();
}
log.info("end---------");
}
}
等待线程ThreadB:
package com.example.demo.synchronize;
import lombok.extern.slf4j.Slf4j;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadB implements Runnable {
private Object lock;
public ThreadB(Object obj) {
lock = obj;
}
@Override
public void run() {
log.info("begin---------");
try {
synchronized (lock) {
log.info("wait------");
lock.wait();
//通知线程结束后才开始唤起其它线程。
log.info("being notified------");
TimeUnit.SECONDS.sleep(new Random().nextInt(3));
}
}catch (Exception e){
e.printStackTrace();
}
log.info("end---------");
}
}
通知线程ThreadC:
package com.example.demo.synchronize;
import lombok.extern.slf4j.Slf4j;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Slf4j
public class ThreadC implements Runnable {
private Object lock;
public ThreadC(Object obj) {
lock = obj;
}
@Override
public void run() {
log.info("通知线程begin---------");
try {
synchronized (lock) {
TimeUnit.SECONDS.sleep(new Random().nextInt(5)+5);
log.info("通知线程notify other------");
lock.notifyAll();
}
}catch (Exception e){
e.printStackTrace();
}
log.info("通知线程end---------");
}
}
执行结果是:ThreadC结束后,ThreadA和ThreadB才会继续执行
00:58:58.876 [Thread-0] INFO com.example.demo.synchronize.ThreadA - begin---------
00:58:58.876 [Thread-1] INFO com.example.demo.synchronize.ThreadB - begin---------
00:58:58.876 [Thread-2] INFO com.example.demo.synchronize.ThreadC - 通知线程begin---------
00:58:58.876 [Thread-0] INFO com.example.demo.synchronize.ThreadA - wait------
00:58:58.876 [Thread-1] INFO com.example.demo.synchronize.ThreadB - wait------
00:59:06.878 [Thread-2] INFO com.example.demo.synchronize.ThreadC - 通知线程notify other------
00:59:06.878 [Thread-2] INFO com.example.demo.synchronize.ThreadC - 通知线程end---------
00:59:06.878 [Thread-1] INFO com.example.demo.synchronize.ThreadB - being notified------
00:59:08.879 [Thread-0] INFO com.example.demo.synchronize.ThreadA - being notified------
00:59:08.879 [Thread-1] INFO com.example.demo.synchronize.ThreadB - end---------
00:59:09.880 [Thread-0] INFO com.example.demo.synchronize.ThreadA - end---------