加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

object.wait(long timeout)方法需要慎用

(2011-11-03 19:25:50)
标签:

杂谈

分类: android

object.wait(long timeout)方法需要慎用(zz)- -

                                      

这篇文章用代码讲解object.wait(long timeout)方法的使用.


还是关于wait()这个方面的话题,Object类除了提供wait()这个方法之外,还提供了另外一方法,那就是wait(long timeout);
javadoc上对这个方法的说明是:
Causes current thread to wait until either another thread invokes the notify() method or the notifyAll() method for this object, or a specified amount of time has elapsed.
于是我想测试一下如果没有另外的线程来调用notify()或者notifyAll(), 那么wait()方法真的可以在指定的时间内返回么?
试想一下,如果一个线程t1中对一个object.wait(1000), t1进入阻塞并且释放object的monitor, 线程t2获得了object的monitor, 如果t2握住object的monitor超过了1000毫秒,比如5000毫秒,那么t1的wait(1000)方法还可能在系统的时钟经过了1000毫秒之后正常返回吗?如果可以返回,t1必须要获得object的monitor, 而这个时候t2并没有释放object的monitor, 所以t1根本就不能够正常返回,下面的代码可以证实这一点。

public class WaitForSpecifiedTimeTest {
 
 private Object vitual = new Object();
 
 public void sleepFor(long mills)
 {
  synchronized(vitual)
  {
   long now = System.currentTimeMillis();
   System.out.println("be going to sleep");
   try {
    vitual.wait(mills);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("I've slept for "+(System.currentTimeMillis()-now)+" mills!");
  }
 }
 
 public void startAnotherThread()
 {
  Thread t = new Thread(){
   public void run()
   {
       try {
             sleep(300);//睡一下的作用是确保让main线程先获得vitual的monitor.
        } catch (InterruptedException e1) {
             e1.printStackTrace();
        }
       synchronized(vitual)
       {
             long now = System.currentTimeMillis();
             System.out.println("I get the monitor");
             try {
                  Thread.sleep(5000);
                  //睡一下的目的是推迟5秒释放vitual的锁,5秒的时间已经超过了wait()的等待时间,这样可以看看程序有什么异常行为。
             } catch (InterruptedException e) {
                  e.printStackTrace();
            }
            System.out.println("I hold the monitor for "+(System.currentTimeMillis()-now)+" mills");
       }
    }
  };
  t.start();
 
 }
 
 public static void main(String []args)
 {
  WaitForSpecifiedTimeTest test = new WaitForSpecifiedTimeTest();
  test.startAnotherThread();
  test.sleepFor(3000);
 
 }
}

我的机器的运行结果是:
be going to sleep
I get the monitor
I hold the monitor for 4997 mills
I've slept for 5308 mills!

也就是说vitual.wait(3000), 它一直睡了5308毫秒才返回。
结论是:这个方法有比较大的潜在的危险,使用的时候一定要慎用,最好不要依赖它。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有