线程(五)--sleep和wait的区别

    上次我们讲完了锁机制,接下来说一下sleep 和wait对锁的控制。
  
   sleep方法是Thread类的静态方法,表示在指定的毫秒数内让当前正在执行的线程休眠。
   wait方法则是Object类的普通方法,表示当前线程等待,直到其他线程调用这个对象的notify()或者notifyAll()方法。

   正如在上文中所说的, java引入了同步监视器来解决线程同步问题,使用同步监视器的通用方法就是同步代码块。其语法格式如下:
   synchronized  (obj) {
                        
                  }
 

 其中obj就是同步监视器,上面代码的含义是:线程开始执行同步代码块之前,必须先获得对同步监视器的锁定。任何时候只能有一条线程可以获得对同步监视器的锁定。同步代码执行结束后,该线程自然释放了对同步监视器的锁定。
  
  因为wait会对线程的同步监视器进行操作, 所以它们必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。  


  sleep和wait具有使当前线程沉睡的作用,最为重要的一个区别就是sleep是Thread类的静态方法,因此他不能改变对象的锁。 所以当在一个Synchronized方法中调用sleep()时,线程虽然休眠了,但是对象的锁没有被释放,其他线程仍然无法访问这个对象。而wait()方法则会在线程休眠的同时释放掉机锁,其他线程可以访问该对象。

  下面我们通过一个例子,来深入了解一下:

/**
 * Thread sleep和wait区别
 *  @author  liubing
 *
 */
public   class  TestSleepAndWait  implements  Runnable {
     int   number  = 10;

     public   void  firstMethod()  throws  Exception {
         synchronized  (  this ) {
             number  += 100;
            System.  out .println(  number );
        }
    }

     public   void  secondMethod()  throws  Exception {
         synchronized  (  this ) {
             /**
             * (休息2S,阻塞线程)
             * 以验证当前线程对象的机锁被占用时,
             * 是否被可以访问其他同步代码块
             */
             //Thread.sleep(2000);
             this .wait(2000);
             number  *= 200;
        }
    }

     @Override
     public   void  run() {
         try  {
            firstMethod();
        }  catch  (Exception e) {
            e.printStackTrace();
        }
    }

     public   static   void  main(String[] args)  throws  Exception {
      TestSleepAndWait testSleepAndWait =  new  TestSleepAndWait();
        Thread thread =  new  Thread(testSleepAndWait);
        thread.start();
        testSleepAndWait.secondMethod();
    }
}

  

  你能猜出打印的number值是多少吗?
  当使用  this.wait(2000) 时,打印的number值是 110
  当使用 Thread.sleep(2000)时,打印的number值是2100

  简单分析一下代码:
  这个类有两个同步方法,也就是任何一个方法执行时, TestSleepAndWait类的对象都会被锁定,导致其他方法等待。
  
 1. 我们先来看使用wait方式时的情况:
  主线程main方法开始执行,  调用thread.start()方法时,线程进入就绪状态,等待cpu调度。接下来会调用 TestSleepAndWait类的 secondMethod()方法,该方法的执行会先于thread的run方法。
  因此,当 secondMethod()方法调用时, testSleepAndWait对象首先被main线程锁定, 随后主线程进入等待。由于wait方法会使得main线程释放对 testSleepAndWait对象的锁定,因此 thread线程获得对 testSleepAndWait对象的锁定, 得到执行机会,run方法开始执行,number初始值10,加上100后,打印出110.

 2. 再来看使用sleep方式时的情况:
  
    主线程main方法开始执行,  调用thread.start()方法时,线程进入就绪状态,等待cpu调度。接下来会调用 TestSleepAndWait类的 secondMethod()方法,该方法的执行会先于thread的run方法。
  因此,当 secondMethod()方法调用时, testSleepAndWait对象首先被main线程锁定, 随后主线程进入等待。由于sleep方法仍然保持对 testSleepAndWait对象的锁定,因此thread线程虽然处于就绪状态,但是由于无法获得对 testSleepAndWait对象的锁定, firstMethod()无法执行。
  两秒钟后,main线程继续执行 secondMethod()方法 ,number乘以200变成2000.
   secondMethod()方法执行完毕,对象锁被释放。
  此时thread线程终于获得对 testSleepAndWait对象的锁定,开始执行 firstMethod(),打印出2100.

  不知道你看明白了没有。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值