A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 yuanjun52306 于 2016-6-20 00:28 编辑

刚才复习的时候感觉这里有点迷糊,就百度了一下,又看了一下冯佳老师的视频和笔记,感觉更迷糊了....
笔记里是这么写的:
wait方法可以传入参数也可以不传入参数,传参数就是在参数的时间结束后等待,不传入参数就是直接等待(这里的等待指的是线程进入阻塞状态)
冯佳老师在视频里是这么说的:

比方说wait(1000); 那就是过了1秒后等待   wait(); 就是直接等待

后面不带参数的我可以理解,就是说必须用notify()或notifyAll()唤醒,否则会一直阻塞
前面带参数的,如果按照视频说的,1秒后等待,那也就是1秒后进入阻塞状态,也必须用notify()或notifyAll()唤醒,否则也会一直陷入阻塞状态


我查了百度和JDK文档,里面说的也是很模糊
JDK文档是这么说的:
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。

我在百度里找到这么个问题:
利用Thread. wait( )同步线程,可以设置超时时间吗?
答案是可以.    里面有一个回答是:
wait(n), 参数 0 时无限长 , 负数会抛 java.lang.IllegalArgumentException 异常 . 等待 n 毫秒,一旦时间到了 , 就自动进入就绪队列

这句话我的理解是: 比方说wait(1000); 那就是过了1秒后,自动进入就绪状态(并非阻塞状态),和sleep(1000)的效果是一样的(这里不考虑锁的释放问题,只考虑时间到后线程的状态问题)


如果这种说法是对的,那么可以理解为wait()里传入的参数是超时时间,超过这个时间,线程就会自动进入就绪队列,等待cpu分配执行权,并不需要notify()或notifyAll()唤醒,这就和视频和笔记上说的矛盾了.


我也在eclipse里面测试过了,wait(1000)和sleep(1000)都放在同步代码块里,效果一样.


希望懂的哥们进来说一下


5 个回复

倒序浏览
我又看了一下文档,里面对于传入的参数的解释是这样的:
timeout - 要等待的最长时间(以毫秒为单位)。
回复 使用道具 举报
其实研究这个问题,主要是怕面试的时候,如果老师问:调用wait()方法,必须手动唤醒吗?
我想应该这么回答:如果不传参数,则必须手动唤醒,如果传入负数会报异常,传入0和不传入是一样的,都是无限等待,必须手动唤醒,传入大于0的数则会暂时进入阻塞状态并释放锁,时间到后自动进入就绪状态,等待cpu分配执行权

(补充)JDK文档:
此方法导致当前线程(称之为 T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度目的,在发生以下四种情况之一前,线程 T 被禁用,且处于休眠状态:

其他某个线程调用此对象的 notify 方法,并且线程 T 碰巧被任选为被唤醒的线程。
其他某个线程调用此对象的 notifyAll 方法。
其他某个线程中断线程 T。
大约已经到达指定的实际时间。但是,如果 timeout 为零,则不考虑实际时间,在获得通知前该线程将一直等待。
然后,从对象的等待集中删除线程 T,并重新进行线程调度。然后,该线程以常规方式与其他线程竞争,以获得在该对象上同步的权利;一旦获得对该对象的控制权,该对象上的所有其同步声明都将被恢复到以前的状态,这就是调用 wait 方法时的情况。然后,线程 T 从 wait 方法的调用中返回。所以,从 wait 方法返回时,该对象和线程 T 的同步状态与调用 wait 方法时的情况完全相同。

点评

赞!  发表于 2016-6-20 21:25
回复 使用道具 举报
wait方法在传入参数时, 马上进入等待状态, 时间到了之后会自动醒来, 不需要唤醒. 效果与sleep差不多, 唯一不同的地方在于, wait方法在进入等待状态后是会释放锁对象的, 而sleep方法在休眠时是不会释放锁对象的. 而且wait方法在时间到了之后醒来了, 并不能马上执行, 需要再次获取到锁对象才能够执行, 所以等待的这个时间可能会比传入的时间值更久一些.
回复 使用道具 举报
龚冼敏老师 发表于 2016-6-20 10:11
wait方法在传入参数时, 马上进入等待状态, 时间到了之后会自动醒来, 不需要唤醒. 效果与sleep差不多, 唯一 ...

明白了,感谢老师的解答!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马