线程的阻塞

阻塞的方法有:
1. sleep() 方法:
sleep() 允许 指定以毫秒为单位的一段时间作为参数,它使得线程 在指定的时间内进入阻塞状态,不能得到CPU 时间,指定的时间一过,线程重新进入可执行状态。典型地,sleep() 被用在等待某个资源就绪的情形:发现条件不满足后,让线程阻塞一段时间后重新测试,直到条件满足为止。  

2. suspend() 和 resume() 方法:
两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用 resume() 使其恢复。  

3. yield() 方法:
yield() 使得 线程放弃当前分得的 CPU 时间,但是不使线程阻塞, 即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间从而转到另一个线程。  

4.   wait() 和 notify() 方法:两个方法配套使用,wait() 使得线程进入阻塞状态,它有两种形式,一种允许 指定以毫秒为单位的一段时间作为参数,另一种没有参数,前者当对应的 notify() 被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的 notify() 被调用。  
初看起来它们与 suspend() 和 resume() 方法对没有什么分别,但是事实上它们是截然不同的。区别的核心在于,前面叙述的所有方法(1、2、3),阻塞时都不会释放占用的锁(如果占用了的话),而这一对方法则相反。  
另外,前面叙述的所有方法都隶属于 Thread 类,但是这一对却直接隶属于 Object 类,也就是说,所有对象都拥有这一对方法(如Integer类型)。初看起来这十分不可思议,但是实际上却是很自然的,因为这一对方法阻塞时要释放占用的锁,而锁是任何对象都具有的,调用任意对象的 wait() 方法导致线程阻塞,并且该对象上的锁被释放。而调用任意对象的notify()方法则使因调用该对象的 wait()方法而阻塞的线程中随机选择的 一个(只是一个)解除阻塞(但要等到获得锁后才真正可执行)。notifyAll() 也可起到类似作用,区别在于,调用notifyAll() 方法将把所有线程一次性全部解除阻塞,然后获得synchronized同步对象的线程可以往下执行,这里要注意:只能同时一个线程获得该synchronized对象,然后该线程释放synchronized对象之后,其它线程便可获得该对象,从而往下执行,注意,没有获得该对象的线程只在等待该对象,不会在wait上阻塞,因为notifyAll()已经把所有的wait都解锁了,如下面代码:
public  static  void  main(String[] args)  throws  InterruptedException {
     final  Object obj =  new  Object();
     new  Thread() {
         @Override
         public  void  run() {
             synchronized  (obj) {
                 try  {
                     obj.wait();
                     Thread.sleep( 500 );
                 catch  (InterruptedException e) {
                 }
                 System.out.println( "thread_1" );
             }
         }
     }.start();
     new  Thread() {
         @Override
         public  void  run() {
             synchronized  (obj) {
                 try  {
                     obj.wait();
                     Thread.sleep( 500 );
                 catch  (InterruptedException e) {
                 }
                 System.out.println( "thread_2" );
             }
         }
     }.start();
     new  Thread() {
         @Override
         public  void  run() {
             synchronized  (obj) {
                 try  {
                     obj.wait();
                     Thread.sleep( 500 );
                 catch  (InterruptedException e) {
                 }
                 System.out.println( "thread_3" );
             }
         }
     }.start();
     Thread.sleep( 1000 );
     synchronized  (obj) {
         obj.notifyAll();
     }
}
输出:
thread_3
thread_2
thread_1
可见所有的wait阻塞都被唤醒,上面代码中notifyAll()等价于3个notify()

注意:
wait()、notify()和notifyAll()都必须放置在synchronized方法或块中,否则会报错(IllegalMonitorStateException),但synchronized方法或块不一定都用到这一对方法

解锁后,线程 沿着wait方法之后 的路径继续执行,注意是 沿着wait方法之后,不是回到同步块

如:
IntegerA = 0;
public void mehtod1(){
synchronized (A) {
      while(true)
      if(A<=0)
      //调用wait()之后,就会释放对象A的锁,这样method2才有机会取得A的锁,进而让A自增
       A.wait();
       else
       A--; 
     }
}
public void method2(){
synchronized (A) {
   //唤醒等待该对象的线程,但是method1不会马上执行,因为A对象的锁还没有释放
   A.notify();
   A++;
  }
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://my.oschina.net/u/1987489/blog/491311

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值