等待/通知机制
什么是等待通知机制
在单线程中,要执行的操作需要满足一定的条件才能执行,可以把这个操作放在if语句块中。
在多线程中,可能A线程的条件没有满足只是暂时的,稍后可能B线程会更新使得A线程的条件得到满足。所以可以将A线程暂停,直到它的条件得到满足后再将A线程唤醒。伪代码如下:
atomics{ //原子操作
while(条件不成立){
等待
}
条件满足后,继续执行操作。
}等待/通知机制的实现
Object类中的wait()方法可以使执行当前代码的线程等待,暂停执行,直到接到通知或被中断为止。
注意:
1.wait()方法只能在同步代码块中由锁对象调用。
2.调用wait()方法,当前线程会释放锁。
伪代码如下:
//在调用wait()方法之前必须获得对象锁
synchronized(锁对象){
while(条件不满足){
锁对象.wait(); //通过锁对象调用wait()方法暂停线程,会释放锁对象。
}
//条件满足,线程向下执行。
}Object类中的notify()可以唤醒线程,该方法也必须在同步代码块中由锁对象调用。没有使用锁对象调用会抛出illegalMonitorStateExepition异常。如果有多个等待线程,notify()只能唤醒其中的一个。在同步代码块中调用notily()方法后,并不会立即释放锁对象,需要等当前同步代码块执行完后才会释放锁对象,一般将notify()方法放在同步代码块的最后。伪代码如下:
synchronized(锁对象){
//修改保护条件代码
锁对象.notify(); //唤醒其他线程;
}
测试代码:
static String lock="lock";
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
System.out.println("线程1开始等待"+" "+System.currentTimeMillis());
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1已经唤醒"+" "+System.currentTimeMillis());
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
System.out.println("线程2开始唤醒"+" "+System.currentTimeMillis());
lock.notify();
System.out.println("线程2结束唤醒"+" "+System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t1.start();
Thread.sleep(1000);
t2.start();
}interrupt()方***中断线程的wait()等待
当线程处于wait()等待状态时,调用线程对象的interrupt()方***中断线程的等待状态,会产生InterruptedException异常。
结果:
notify()与notifyAll的区别
notify()一次只能唤醒一个线程,如果有多个线程需要唤醒,notify()只能随机的唤醒其中的一个。notifyAll()可以唤醒所有的线程。
final static Object object=new Object();
public static void main(String[] args) throws InterruptedException {
Thread thread01= new Thread(new Runnable() {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " 开始等待");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 等待结束");
}
}
});
Thread thread02= new Thread(new Runnable() {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " 开始等待");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 等待结束");
}
}
});
Thread thread03= new Thread(new Runnable() {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " 开始等待");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 等待结束");
}
}
});
Thread thread04= new Thread(new Runnable() {
@Override
public void run() {
synchronized (object) {
System.out.println(Thread.currentThread().getName() + " 开始唤醒");
object.notifyAll();
System.out.println(Thread.currentThread().getName() + " 唤醒结束");
}
}
});
thread01.start();
thread02.start();
thread03.start();
Thread.sleep(5000);
thread04.start();
}全部唤醒结果:
wait(long) 方法
如果在long时长内线程没有被唤醒,那么这个线程会自动唤醒。
通知过早
当线程等待唤醒之前就执行了唤醒操作,可能就会影响程序正常的工作流程。

京公网安备 11010502036488号