文档中对wait(long   timeout)的说明如下:等待一个条件的发生,如果在设定的时间内没有收到通知,就返回.   
  现有疑问如下:if   线程甲调用一个对象锁的syncronize函数,函数中进入了wait(time),则释放此对象锁.线程乙的syncronize函数获得此对象锁,运行,但尚未释放锁,此时timeout时间到.此时wait(timeout)仍可返回么?(矛盾如下:若返回则意味线程甲重新获得对象锁,但此时乙又未释放锁)   
  望各位高手解释一下,感激不尽

解决方案 »

  1.   

    线程甲会一直等待线程乙释放对象锁,然后才可以开始执行。这一点与乙调用notify唤醒甲的过程是相同的,线程甲并不是马上可以执行。
    但与调用notify不同的是,线程甲的wait方法不会抛出异常,只是正常的返回。而notify唤醒时,wait方法会抛出异常
      

  2.   


    "线程甲会一直等待线程乙释放对象锁" 如果这种说法是正确的,那么wait(timeout) 中的timeout参数好象没有意义了,按你的说法,即使timeout时间到了,还是要一直等待线程乙释放对象锁,那为什么要设置timeout参数呢? 所以,最好我们写一些代码验证一下. 究竟timeout以后,线程甲会如何动作.  
      

  3.   

    因为这是两种完全不同的效果,我已经强调了,notify唤醒会抛出异常,超时唤醒不会抛出
    那个线程甲就可以根据有没有出现异常来进行不同的逻辑处理
      

  4.   

    举个例子,当连接池中所有连接都被占满以后,可以调用wait(10000)来等待其它线程释放连接,但是如果超过10秒都没有人释放(即没有调用notify)时,则可以退出等待告诉前端用户没有可用的连接
      

  5.   

    我觉得可能会抛出 IllegalMonitorStateException (如果当前线程不是此对象监视器的所有者) 这个exception。 因为timeout了,线程甲还不是此对象监视器的所有者,所以抛出这个exception.  当然只是个人估计,没写代码验证.
      

  6.   

    timeout最大作用是设置最大等待时间,而不是无穷无尽的等待---点太快了,搞到连续回了几贴
      

  7.   


    这个是肯定不会的,线程甲一定会在等待别人释放对象锁。
    不过我上面说的有错,应该无论notify还是timeout都不会抛出异常才对,这个是我记错了。
      

  8.   


    你不是说线程甲会一直等待吗? 如何它一直在等待,就不会跳出来了,也就是不会执行wait语句之后的代码了,也就是说没办法退出等待呀. 另外,如果是真的退出等待了(好象跟你说的一直等待有矛盾了),那么这时锁的所有者是线程B吗?  这就是楼主问的问题. 
      

  9.   


    恩,我也觉得是不会抛出异常的。刚刚已经回帖了,但是 CSDN 总是报什么错误,回不上。等再来回,发现意见一致了。
      

  10.   


    我觉得是这样的:
    情况1:如果当甲在等待的时间结束后,wait就返回。
    但由于同步的约束,
    甲如果这个时候获得了对象的锁,那么可以向下执行。获得锁的途径就是乙此时已经释放了对象锁。
    甲如果这个时候没有获得对象的锁,则一直阻塞,直到它能获得对象锁,得以向下继续。如果不能,就一直等待。情况2:如果当甲还没有到达等待的时间,
    而此时线程乙已经退出,并释放了对象的锁。
    如果这个时候,乙调用了锁的notify()方法,则甲不需要再去等待剩余的时间过去,直接醒来,继续向下。如果这个时候,乙并没有调用notify()方法,则甲就要等待剩余的时间过去,自己醒来。(因为这时候乙已经释放了锁,甲就得到了锁,可以向下。如果在甲wait剩余时间的时候,丙获得了锁,则甲还得等。)
      

  11.   

    调用notify的前提必须是已经取得对象的锁,否则会抛出异常的如果在乙没有释放锁的时候调用了notify,甲是会被唤醒被处于等待乙释放锁的状态,当乙释放了锁时,甲就可以开始执行了
      

  12.   

    UP。有问题大家帮忙。
    做个广告:
    http://topic.csdn.net/u/20090120/15/38aeb61f-4cd5-43e9-a56d-f3ab036d8d59.html这个帖子急需各位高人解答。谢谢!
      

  13.   

    抽时间写了代码验证了一下:
    结论: 甲会一直等待乙释放锁才会继续, 即使乙调用了notifyAll甲一样会等待; 即使timeout 时间到了甲也会一直等待. 有一点不明白:timeout参数似乎没有用,无论设置什么值都是要等待乙释放锁.甲不会因为timeout时间到了而去继续执行正面的代码. 所以,我暂时还搞不懂什么情况下用timeout这个参数. 以下是代码,如有错误请指正.
    public class Test{
    public String msg = "aa";
    public static void main(String[] args){
    Thread1 t1 = new Thread1();
    Thread2 t2 = new Thread2();
    Test test = new Test();
    t1.test = test;
    t2.test = test;
    t1.start();
    t2.start();
    }
    }
    public class Thread1 extends Thread{
    public Test test;
    public void run(){
    synchronized(test){
    try {
    System.out.println("tread1 start to wait.");
    test.wait(100); //这里时间设置多少都一样,似乎不起作用.
    System.out.println("tread1 completed waiting.");
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    test.msg = "bb";
    System.out.println("thread1 set value:" + test.msg);
    System.out.println("thread 1 done");
    }
    }
    }
    public class Thread2 extends Thread{
    public Test test;
    public void run(){
    try {
    sleep(10);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    synchronized(test){
    try {
    System.out.println("Tread2 locked");
    System.out.println("Tread2 notifyAll");
    test.notifyAll(); //这句用不用tread1都不会继续运行
    sleep(3000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println("thread 2 unlocked");
    }

    }
    }
      

  14.   

    打印结果:
    tread1 start to wait.
    Tread2 locked
    Tread2 notifyAll
    thread 2 unlocked //这里可以看到,tread1必须等待tread2 解锁后,才能继续,无认是否timeout或执行notifyAll都一样.
    tread1 completed waiting.
    thread1 set value:bb
    thread 1 done
      

  15.   

    timeout的用处我已经说了N次了,就是为了不会无限的等待下去。
    如果不存在线程乙,wait()方法是无限的等待下去,
    而wait(10000)则在10秒后返回并可以继续执行下面的代码(很多情况下超时处理与被线程乙唤醒的处理逻辑不太一样)
    是调用wait()还是wait(10000)是你代码本身逻辑需要考虑的事情
      

  16.   


    可是实际情况并不是你说的呀,如果thread2 不解锁,它还是会无限等待下去,即使你设置了timeout时间, 你可以试试运行我的代码
      

  17.   

    那个是因为线程乙已经取得锁的问题,与wait函数有参数与否根本没有关系
    更多的情况下,notify后线程乙就会释放锁,使得线程甲可以开始运行
      

  18.   

    答:显然楼主对等待的内部机制不明白.
    1)JAVA中任何对象内部有两个等待队列:一个是wait等待队列,另一个是对象锁等待队列.
    2)当用wait(timeout)等待时:第一步:释放锁,第二步:该线程进入该对象的wait等待队列之中.
      当wait(timeout)时间已到时,该线程一定会醒来,从wait等待队列中移出来,此时(该线程已是运行态,wait的任务已经完成了):该线程将试图再次获取对象的锁,(目的:从上次的wait的断点处,试图继续运行下去),若锁获取成功,则从上次的wait的断点处,继续运行下去.若锁获取不成功,则该线程将进入该对象的锁等待队列去等待对象锁了.这是两种不同的等待啊.