wait() notify()
在Object.java中,定义了wait(), notify()和notifyAll()等接口。wait()的作用是让当前线程进入等待状态,同时,wait()也会让当前线程释放它所持有的锁。而notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
Object类中关于等待/唤醒的API详细信息如下:
notify() -- 唤醒在此对象监视器上等待的单个线程。
notifyAll() -- 唤醒在此对象监视器上等待的所有线程。
wait() -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。wait()=wait(0),表示无线等待
wait(long timeout) -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。
wait(long timeout, int nanos) -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量”,当前线程被唤醒(进入“就绪状态”)。
yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是当前线程又进入到“运行状态”继续运行!
sleep()的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。
join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行。
Interrupt():中断线程
tips:wait()和notify()都会放弃对象监视器的区别:wait()方法会立刻释放对象监视器,notify()方法会等待线程剩余代码执行完毕才会放弃对象监视器。
sleep是自己到期自己唤醒
wait是被别人唤醒
Wait、sleep和yield区别
(01) wait()是让线程由“运行状态”进入到“等待(阻塞)状态”,而yield()是让线程由“运行状态”进入到“就绪状态”。sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。
(02) wait()是会线程释放它所持有对象的同步锁,而yield()、sleep()方法不会释放锁。
(03) wait()和notify(),notifyAll()是Object类的方法,sleep()和yield()是Thread类的方法.
注意:wait()让当前线程处于“等待(阻塞)状态”,当前线程不是t1!!!!,而是运行的main主线程。
当两个线程同时访问同一资源时,需要使用synchronized
(1).调用notify是随机的唤醒某一thread.而notifyAll则是唤醒所有等待的线程, 但只有一个线程可以在唤醒后lock object monitor,所以, notifyAll操作也是有利弊的.
(2).wait、notify、notifyAll必须在synchronized修饰的代码块中执行,否则会在运行的时候抛出IllegalMonitorStateException异常 (成功调用wait方法的先决条件是当前线程获取到监视器对象上的锁)
(3).在循环语句wait的时候一定要设定循环的条件--这样能够避免wait开始之前,线程所需的条件已经被其他线程提供了却依然开始此线程wait导致的时间消耗。同时,这种办法还能够保证你的代码不被虚假的信息唤醒。
(4).总是要保证在调用notify和notifyAll之前,能够提供符合线程退出等待的条件。否则会出现即使线程接收到通知信息,却不能退出循环等待的情况。
Yield
放弃当前CPU的资源,让给其他任务去占用CPU的时间