Java wait、notify、notifyAll&线程的基本状态

在开始学习wait、notify和notifyAll 之前,先稍微讲讲wait set。所有实例都有一个wait set,wait set是一个在执行该实例的wait方法时、操作停止的线程的集合它有点类似线程的休息室,而且每个实例都会有。
执行wait方法时,线程便会暂时停止操作,进入 wait set这个休息室。除非发生下列其中一种情况,否则线程会永远被留在这个wait set 里。

  1. 有其他线程以notify 方法唤醒该线程;
  2. 有其他线程以notifyA方法唤醒该线程;
  3. 有其他线程以interrupt方法唤醒该线程;
  4. wait 方法已经到期。
     

Wait方法——把线程放入wait set:

obj.wait();

则目前的线程停止执行,进入实例obj的的wait set.这个操作成为:

        线程在obj上wait().(这个obj不是线程而是对象)

        wait();  this.wait();意义相同,执行wait的线程就会进入this的wait set.此时就变成了在this上wait.

如欲执行wait()方法,线程需获取锁定(这是规则)。

但是当线程进入wait set时,已经释放了该实例的锁定。


Notify方法——从wait set拿出线程:

obj.notify();(这个obj也是对象,不是线程)则从wait set里的线程中挑出一个,唤醒这个线程。被唤醒的线程便退wait set

        Notify后的线程:

被notify唤醒的线程不是在notify后立即执行,因为在notify的那一刻,执行notify 的线程还握着锁定不放,所以其他线程无法获取该实例的锁定。需要重新争夺锁。      

        Notify如何选择线程:

假设执行notify方法时,wait set里面正在执行的线程不止一个。规格并没有注明此时该选择哪一个线程。究竟是选择等待线程里面的第一个,随机选择或是另以其他方式选择,则以java处理系统而异。  


notifyAll()方法——从wait set 拿出所有线程:

跟wait方法和notify方法一样,线程必须要获取要调用实例的锁定,才能调用notifyAll方法。

若没有锁定的线程去调用wait,notify或notifyAll时,便会抛出异常java.lang.IllegalMonitorStateException.

Notify方法和notifyAll方法两者非常相似,到底该用哪一个?老实说,这个选择有点难。选择notify的话,因为要唤醒的线程比较少,程序处理速度当然要比notifyAll略胜一筹。但是选择notify时,若这部分程序处理的不好,可能会有程序挂掉的危险性,一般说来,选择notifyAll所写出来的程序代码要比选择notify可靠。除非你能确定程序员对程序代码的意义和能力限度一清二楚,否则选择notifyAll应该比较稳扎稳打


注意:

wait,notify,notifyAll是Object类的方法

obj.wait()是把现在的线程放到obj的wait set

obj.notify()是从obj的wait set里唤醒一个线程

obj.notifyAll()是唤醒所有在obj的wait set里的线程

换句话说,把wait、notify、notifyAll三者均解释为对实例对象的wait set的操作,会比说他们是对线程的操作更贴切,由于所有实例都会有wait set,所以wait、notify、notifyAll才会是Object类的方法。

虽然三者不是Thread类固有的方法,不过,因为Object类是Java所有类的祖先类,所以wait、notify、notifyAll也是Thread的方法。


线程的状态:

1. 新建( new ):新创建了一个线程对象。

2. 可运行( runnable ):线程对象创建后,其他线程(比如 main 线程)调用了该对象 的 start ()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取 cpu 的使用权 。

3. 运行( running ):可运行状态( runnable )的线程获得了 cpu 时间片( timeslice ) ,执行程序代码。

4. 阻塞( block ):阻塞状态是指线程因为某种原因放弃了 cpu 使用权,也即让出了 cpu timeslice ,暂时停止运行。直到线程进入可运行( runnable )状态,才有 机会再次获得 cpu timeslice 转到运行( running )状态。阻塞的情况分三种:

Blocked(堵塞)状态:

  • 同步锁;
  • 调用了sleep()和join()方法进入Sleeping状态;
  • 执行wait()方法进入Waiting状态,等待其他线程notify通知唤醒);
  1. (一). 等待阻塞:运行( running )的线程执行 o . wait ()方法, JVM 会把该线程放 入等待队列( waitting queue )中。
  2. (二). 同步阻塞:运行( running )的线程在获取对象的同步锁时(synchronized),若该同步锁被别的线程占用,则 JVM 会把该线程放入锁池( lock pool )中。
  3. (三). 其他阻塞: 运行( running )的线程执行 Thread . sleep ( long ms )或 t . join ()方法,或者发出了 I / O 请求时, JVM 会把该线程置为阻塞状态。当 sleep ()状态超时、 join ()等待线程终止或者超时、或者 I / O 处理完毕时,线程重新转入可运行( runnable )状态。

5. 死亡( dead ):线程 run ()、 main () 方法执行结束,或者因异常退出了 run ()方法,则该线程结束生命周期。死亡的线程不可再次复生。

在java中官方是这么定义的:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值