首页 > 编程 > Java > 正文

Java多线程系列(4)--线程等待与唤醒

2019-11-08 01:25:57
字体:
来源:转载
供稿:网友

一、wait()、notify()、notifyAll()等方法基本概述

在Object.java中,定义了wait()、notify()和notifyAll()等接口。wait()的作用就是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的的锁;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。 上述方法的详细信息如下: notify() –唤醒在此对象监视器上等待的单个线程; notifyAll() –唤醒在此对象监视器上等待的所有线程; wait() —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,当前线程被唤醒(进入就绪状态); wait(long timeout) —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,或者超过指定的时间量,当前线程被唤醒(进入就绪状态); wait(long timeout,int nanos) —-让当前线程处于“等待(阻塞)状态”。直到其它线程调用此对象的notify()方法或者notifyAll()方法,或者超过指定的时间量,或者其它某个线程中断当前线程,当前线程被唤醒(进入就绪状态) 二、wait()、notify()、notifyAll()代码实例 由于与wait配合起来使用时,notify()和notifyAll()并无太大区别。下面仅通过wait与notify()代码来进行演示

package Test;/** * Created by LKL on 2017/2/20. */public class TestWaitAndNotify { public static void main(String[] args) throws InterruptedException { MyThread3 t1 = new MyThread3("t1"); // MyThread3 t2 = new MyThread3("t2"); synchronized(t1){ System.out.PRintln(Thread.currentThread().getName()+" start t1"); // System.out.println(Thread.currentThread().getName()+" start t2"); t1.start(); // t2.start(); //主线程等待t1通过notify()唤醒 System.out.println(Thread.currentThread().getName()+" wait() "); t1.wait(); //此时持有t1这个对象的锁的是object System.out.println(Thread.currentThread().getName()+" continue "); } }}package Test;/** * Created by LKL on 2017/2/20. */public class MyThread3 extends Thread{ public MyThread3(String name) { super(name); } public void run(){ synchronized(this){ System.out.println(Thread.currentThread().getName()+" call notify()"); //唤醒当前线程 notify(); } }}

运行结果如下:

main start t1main wait() t1 call notify()main continue

上述流程为: (1)主线程main通过new MyThread3(“t1”)新建线程t1,接着通过synchronized(t1)获取”获取t1对象的同步锁”,然后调用t1.start()启动线程t1。 (2)主线程main执行t1.wait()释放”t1对象的锁”,并且进入了等待(阻塞)状态。等待t1对象上的线程通过notify()或notifyAll()将其唤醒。 (3)线程t1运行之后,通过synchronized(this)获取”当前对象的锁”;接着调用notify()唤醒”当前对象上的得带线程”,此时也就意味着唤醒主线程; (4)线程t1运行完毕之后,会释放当前对象的锁,接着,主线程获取t1对象的锁,然后接着运行。 当把上述代码修改如下时:

package Test;/** * Created by LKL on 2017/2/20. */public class TestWaitAndNotify { public static void main(String[] args) throws InterruptedException { MyThread3 t1 = new MyThread3("t1"); // MyThread3 t2 = new MyThread3("t2"); synchronized(t1){ System.out.println(Thread.currentThread().getName()+" start t1"); // System.out.println(Thread.currentThread().getName()+" start t2"); // t1.start(); // t2.start(); //主线程等待t1通过notify()唤醒 System.out.println(Thread.currentThread().getName()+" wait() "); t1.wait(); //此时持有t1这个对象的锁的是object System.out.println(Thread.currentThread().getName()+" continue "); } }}

也就是不开启t1这个线程,此时主线程main运行了t1.wait()后,一直处于阻塞状态,因为并没有线程将它唤醒。

main start t1main wait()

二、wait()、notify()总结

wait()会使当前线程等待,因为线程进入等待(阻塞)状态,所以线程应该释放它所持有的“同步锁”,否则其它线程获取不到这个“同步锁”而无法运行。 notify()和wait()直接就是依据“对象的同步锁”关联起来的。 假设我们把负责唤醒等待线程的那个线程称为唤醒线程,它只有在获取“该对象的同步锁”,此时的同步锁必须和等待线程的同步锁是同一个,并且调用notify()或调用notifyAll()方法之后,才能唤醒等待线程;但是它不能立刻执行,因为唤醒线程还持有该对象的同步锁,必须等到唤醒线程释放了对象的同步锁之后,等待线程才能获取到对象的同步锁,从而继续运行。 因此,notify()和wait()依赖于同步锁,而同步锁是对象所持有,并且每个对象只有一个。所以,wait()、notify()等方法定义在object类中,而不是Thread类中。

文章只是作为自己的学习笔记,借鉴了网上的许多案例,如果觉得阔以的话,希望多交流,在此谢过…


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表