线程等待机制——wait/notify(notifyAll)

Posted 无赖H4

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程等待机制——wait/notify(notifyAll)相关的知识,希望对你有一定的参考价值。

线程等待机制


wait、notify、notifyAll属于Object类下的三个普通方法
(java中所有对象都具备这三个方法)
基本使用规则:对象.wait(),使得线程进入“等待”状态,直到有其他线程,在同一个对象上调用notify/notifyAll()方法

语法

关于wait和notify的使用规则,必须先对等待的对象,通过synchronized加锁

Object o = new Object();//等待唤醒的对象
synchronized (o)
    o.wait();//如果不这么操作,会收到异常

synchronized(o)
    o.notify();

唤醒的线程如何知道有哪些对象在o这个对象上?
等待集(wait set):保存等在对象上的所有线程
wait:把当前线程加入到等待集中
notify:从wait set删除掉一个线程

由于多个线程修改共享数据,所以需要synchronized保护

wait

wait()的作用就是让当前线程进入等待状态,同时也会让当前线程释放它所持有的锁,直到其他线程调用notify()或notifyAll()方法,被唤醒进入就绪状态;

wait()

wait() / wait(long timeout) / wait(long timeout, int nanos)
time out : 超时
wait什么时候会醒过来:
1、会被别的线程唤醒
2、会在到达超时时间时
3、会在被别的进程打断(interrupt)时->收到一个InterruptException异常
4、由于系统原因,可能出现假唤醒——毫无征兆的醒来

加锁

在o.wait()时,需要进行加锁,当wait成功,会释放锁,但不是释放所有锁,只释放o这把锁.
当wait被唤醒时,会重新对o进行加锁操作

notify

  • notify()会唤醒等待在对象上的一个线程,但是它是随机唤醒
  • notifyAll()会唤醒等待在对象上的所有线程
  • notify()会有状态保留吗?
    例如:当线程A调用了o.notify();线程B在调用o.wait();是等待呢,还是被唤醒?
    A会等待,没有状态保留

使用场景

A线程是等待线程,B线程是唤醒线程
A线程在等待某个条件发生的时候(例如:a==1),当条件没有满足的时候,wait
B线程,会在某些情况下,使得条件成立(a = 1),当条件成立的时候,B有责任唤醒A

A:
if(a != 1
    sync(o)
    o.wait()
    

B:
a = 1;
o.notify();

这里,我们可以将if换为while保证wait又可能唤醒

例子:

import java.util.Scanner;

public class Demo1 
    private static final Object o = new Object();

    static class MyThread extends Thread 
        @Override
        public void run() 
            try 
                System.out.println("我即将进入等待状态");
                synchronized (o) 
                    o.wait();
                
                System.out.println("我被别的线程唤醒了");
             catch (InterruptedException exc) 
                exc.printStackTrace();
            
        
    

    public static void main(String[] args) throws InterruptedException 
        MyThread thread = new MyThread();
        thread.start();

        Scanner s = new Scanner(System.in);
        System.out.println("等待我们的输入,我们不输入,不继续");
        s.nextLine();
        System.out.println("有输入,进行线程的唤醒操作");
        synchronized (o) 
            o.notify();
        
    

wait和sleep对比

Thread.sleep(ms)/TimeUnit.*.sleep()

o.wait();
的区别:

相同现象
1、造成线程的阻塞(停止运行),状态是TIME_WAITING
2、貌似都是等待xx时间后继续运行
差异点
1、wait等待的时间<=timeout,sleep== timeout
2、语义上不同 (核心)
3、锁/wait有锁的释放(不是所有锁);sleep和锁无关
4、写法不同

以上是关于线程等待机制——wait/notify(notifyAll)的主要内容,如果未能解决你的问题,请参考以下文章

线程间的通信----wait/notify机制

sleep,yield,wait,notify,notifyAll

Java多线程--wait(),notify(),notifyAll()的用法

等待 / 唤醒机制(wait / notify)

关于wait/notify

关于wait/notify