java线程wait()与sleep()异同

一、在了解wait()与sleep()前,先来了解一下线程都有哪些状态,各个状态之间是如何转换的?

新建(初始)状态(New):线程对象被创建后进入了新建状态, Thread t = new Thread();

就绪(Runnable):称为:“可执行状态”,当线程被new出来后,其他的线程调用了该对象的start()方法,即thread.start(),此时线程位于“可运行线程池”中,只等待获取CPU的使用权,随时可以被CPU调用。进入就绪状态的进程除CPU之外,其他运行所需的资源都已经全部获得。

运行(Running):线程获取CPU权限开始执行,注意:线程只能从就绪进入到运行状态。

阻塞(Blocked):阻塞状态是线程因为某种原因放弃CPU的使用权,暂时停止运行,知道线程进入就绪状态后才能有机会转到运行状态。

 阻塞情况分三种:

   等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池中”。进入这个状态后是不能自动唤醒的,必须依靠其他线程调用notify()或者notifyAll()方法才能被唤醒。

   同步阻塞:运行的线程在获取对象的(synchronized)同步锁时,若该同步锁被其他线程占用,则JVM会吧该线程放入“锁池”中。

   其他阻塞:通过调用线程的sleep()或者join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新回到就绪状态。

死亡(Dead):线程执行完了或因异常退出了 run() 方法,则该线程结束生命周期。

二、wait()/notify()/notifyAll()

这三个方法都是定义在Object类的,wait的作用是当当前线程释放它所持有的锁进入等待状态,而notify和notifyAll则是唤醒当前对象上的等待线程。

	notify() : 唤醒在此对象监视器上等待的单个线程。
	notifyAll() : 唤醒在此对象监视器上等待的所有线程。
	wait() : 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。
	wait(long timeout) : 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。
	wait(long timeout, int nanos) : 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量”,当前线程被唤醒(进入“就绪状态”)。	

wait() 会释放它所占用的“锁标志”,从而使线程所在对象中的其他 synchronized 数据可以被其他线程使用。waite()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronizedblock中进行调用。如果在non-synchronized函数或non-synchronizedblock中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。

负责唤醒等待线程的那个线程(我们称为“唤醒线程”),它只有在获取“该对象的同步锁”(这里的同步锁必须和等待线程的同步锁是同一个),并且调用notify()或notifyAll()方法之后,才能唤醒等待线程。虽然,等待线程被唤醒;但是,它不能立刻执行,因为唤醒线程还持有“该对象的同步锁”。必须等到唤醒线程释放了“对象的同步锁”之后,等待线程才能获取到“对象的同步锁”进而继续运行。


三、sleep()/yield()

这两个方法定义在 Thread类中。

	sleep():是让当前线程休眠(正在执行的线程主动让出cpu,然后cpu就可以去执行其他任务),即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时候会大于或者等于该休眠时间,当时间过后该线程重新被执行,他会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。
	yield():作用是让步,它能够让当前线程从“运行状态”进入到“就绪状态”,从而让其他等待线程获取执行权,但是不能保证在当前线程调用yield()之后,其他线程就一定能获得执行权,也有可能是当前线程又回到“运行状态”继续运行。相当于,当前线程让出了CPU后,所有线程(包括当前线程)竞争CPU资源,其中,优先级高的不一定能抢到资源,只是概率大一些,也有可能是优先级低的抢占到了CPU资源。

四、wait()与sleep()异同

• 相同点:

	○ 他们都是在多线程的环境下,都可以在程序的调用出阻塞指定的毫秒数并且返回
	
	○ 两个方法都可以通过interrupt()方法打断线程的暂停状态,但是线程会抛出InterruptedException。需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。 
	
• 不同点:

	○ wait(),notify,notifyAll()是Object类;sleep(),yield()是 Thread类
	
	○ synchronized关键字可以和对象的锁交互,sleep()方法不是释放锁,而wait()方法释放锁,使其他线程可以使用同步控制块或方法。
	
	○ wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 。注意:wait()必须放在synchronized block中,否则会在program runtime时扔出“java.lang.IllegalMonitorStateException”异常。
	
	○ sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值