进程、线程状态
进程一般分五个状态:创建,就绪,运行,阻塞,结束
线程一般分四个状态:就绪,运行,阻塞,死亡
针对进程或线程各个状态的区别,从名字大概就可以看出来了。针对阻塞、休眠,挂起,又怎么考虑区别呢?实际使用时,经常称呼阻塞后进入挂起,因为可以认为挂起就是一个动作,进入阻塞态或休眠态。休眠和挂起并没有写入线程、进程生命周期的状态。
1、主动,被动角度
阻塞pend是被动,在访问临界资源(锁等)时,被阻塞了
休眠和挂起,一般是主动(或由父进程发起挂起)因此恢复也应该要主动完成,休眠在休眠时,就知道了计划休眠时长sleep(10),挂起suspend需要等待resume。
时间片到了,也会挂起线程。
2、CPU,内存角度
阻塞会释放CPU,一般不释放内存。
挂起一般会继续占用CPU,一般会释放内存,被转移到外存。
休眠一般会释放CPU,低优先级或其它优先级可以得到执行。也有说sleep()指线程被调用时,占着CPU不工作,形象的说明为“占着CPU”睡觉
3、线程锁等角度
阻塞不会释放锁
挂起会释放锁
休眠也不会释放锁
4、调度角度
任务调度是操作系统来实现的,任务调度时,直接忽略挂起状态的任务,
但是会顾及处于pend下的任务,当pend下的任务等待的资源就绪后,就可以转为ready了。ready只需要等待CPU时间
5、分享网上的两个段子
5.1异步同步阻塞非阻塞
老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张觉得自己有点傻
2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~ 的噪音。
3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大
4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。
5.2 阻塞,挂起,睡眠(休眠)
对线程的控制就好比你控制了一个雇工为你干活。你对雇工的控制是通过编程来实现的。
挂起线程的意思就是你对主动对雇工说:“你睡觉去吧,用着你的时候我主动去叫你,然后接着干活”。
使线程睡眠的意思就是你主动对雇工说:“你睡觉去吧,某时某刻过来报到,然后接着干活”。
线程阻塞的意思就是,你突然发现,你的雇工不知道在什么时候没经过你允许,自己睡觉呢,
但是你不能怪雇工,肯定你 这个雇主没注意,本来你让雇工扫地,结果扫帚被偷了或被邻居家借去了,
你又没让雇工继续干别的活,他就只好睡觉了。至于扫帚回来后,雇工会不会知道,会不会继续干活,你不用担心,
雇工一旦发现扫帚回来了,他就会自己去干活的。因为雇工受过良好的培训。这个培训机构就是操作系统。
sleep()和wait()函数的区别:
(1)两者比较的共同之处是:两个方法都是使程序等待多少毫秒。
(2)最主要区别是:sleep()方法没有释放锁。而wait()方法释放了锁,使得其他线程可以使用同步控制块或者方法。
(3)它们的语法使用不同。Sleep()是线程类(Thread)的方法,当一个线程调用Sleep()方法后,此线程会暂停执行一段时间,将执行机会交给其他线程,但是监控状态依然保持,到设定的时间后会自动恢复,而且可以在任何地方使用。另一方面,wait()是Object类的方法,当一个线程对某个对象调用wait()方法时,会导致本线程放弃该对象的锁,进入等待该对象的等待锁定池中。只有当针对这个对象发出notify()方法或notifyAll()后,本线程才进入对象锁定池准备获得对象锁进入运行状态。
(4)他们的唤醒方式也有所不同。Sleep()方法的唤醒是由时间驱动的,而wait()的唤醒则是通过调用notify()或notifyAll()方法来实现的。