等待与唤醒

Posted myitnews

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了等待与唤醒相关的知识,希望对你有一定的参考价值。

在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。

一、Object类中关于等待/唤醒的API

  • notify() -- 唤醒在此对象监视器上等待的单个线程。
  • notifyAll() -- 唤醒在此对象监视器上等待的所有线程。
  • wait() -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。
  • wait(long timeout) -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。
  • wait(long timeout, int nanos) -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量”,当前线程被唤醒(进入“就绪状态”)。

二、wait和nofity示例

技术图片
// WaitTest.java的源码
class ThreadA extends Thread

    public ThreadA(String name) 
        super(name);
    

    public void run() 
        synchronized (this) 
            System.out.println(Thread.currentThread().getName()+" call notify()");
            // 唤醒当前的wait线程
            notify();
        
    


public class WaitTest 

    public static void main(String[] args) 

        ThreadA t1 = new ThreadA("t1");

        synchronized(t1) 
            try 
                // 启动“线程t1”
                System.out.println(Thread.currentThread().getName()+" start t1");
                t1.start();

                // 主线程等待t1通过notify()唤醒。
                System.out.println(Thread.currentThread().getName()+" wait()");
                t1.wait();

                System.out.println(Thread.currentThread().getName()+" continue");
             catch (InterruptedException e) 
                e.printStackTrace();
            
        
    
View Code

如下图,说明了“主线程”和“线程t1”的流程:
(1) 注意,图中"主线程" 代表“主线程main”。"线程t1" 代表WaitTest中启动的“线程t1”。 而“锁” 代表“t1这个对象的同步锁”。
(2) “主线程”通过 new ThreadA("t1") 新建“线程t1”。随后通过synchronized(t1)获取“t1对象的同步锁”。然后调用t1.start()启动“线程t1”。
(3) “主线程”执行t1.wait() 释放“t1对象的锁”并且进入“等待(阻塞)状态”。等待t1对象上的线程通过notify() 或 notifyAll()将其唤醒。
(4) “线程t1”运行之后,通过synchronized(this)获取“当前对象的锁”;接着调用notify()唤醒“当前对象上的等待线程”,也就是唤醒“主线程”。
(5) “线程t1”运行完毕之后,释放“当前对象的锁”。紧接着,“主线程”获取“t1对象的锁”,然后接着运行。

 

以上是关于等待与唤醒的主要内容,如果未能解决你的问题,请参考以下文章

三等待与唤醒

14 进程的等待与唤醒机制

线程系列三线程的等待与唤醒机制

Linux等待队列与唤醒

等待与唤醒案例

JAVA学习之等待与唤醒案例线程池Lambda表达式