這幾天在看IO和NIO,
說IO是阻塞的,當多個IO訪問服務器時,發生阻塞的時候,CPU要不停的輪詢每個IO的線程,看哪個IO的阻塞解除。會浪費CPU資源。
然后我看了線程的狀態分類,專門有人說過阻塞和同步是不一樣的。
1、新建狀態(New):新創建了一個線程對象。
2、就緒狀態(Runnable):線程對象創建后,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3、運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
4、阻塞狀態(Blocked):阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。阻塞的情況分三種:
(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。
(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
5、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
1、線程的實現有兩種方式,一是繼承Thread類,二是實現Runnable接口,但不管怎樣,當我們new了這個對象后,線程就進入了初始狀態;
2、當該對象調用了start()方法,就進入可運行狀態;
3、進入可運行狀態后,當該對象被操作系統選中,獲得CPU時間片就會進入運行狀態;
4、進入運行狀態后情況就比較復雜了
4.1、run()方法或main()方法結束后,線程就進入終止狀態;
4.2、當線程調用了自身的sleep()方法或其他線程的join()方法,就會進入阻塞狀態(該狀態既停止當前線程,但並不釋放所占有的資源)。當sleep()結束或join()結束后,該線程進入可運行狀態,繼續等待OS分配時間片;
4.3、線程調用了yield()方法,意思是放棄當前獲得的CPU時間片,回到可運行狀態,這時與其他進程處於同等競爭狀態,OS有可能會接着又讓這個進程進入運行狀態;
4.4、當線程剛進入可運行狀態(注意,還沒運行),發現將要調用的資源被synchroniza(同步),獲取不到鎖標記,將會立即進入鎖池狀態,等待獲取鎖標記(這時的鎖池里也許已經有了其他線程在等待獲取鎖標記,這時它們處於隊列狀態,既先到先得),一旦線程獲得鎖標記后,就轉入可運行狀態,等待OS分配CPU時間片;
4.5、當線程調用wait()方法后會進入等待隊列(進入這個狀態會釋放所占有的所有資源,與阻塞狀態不同),進入這個狀態后,是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒(由於notify()只是喚醒一個線程,但我們由不能確定具體喚醒的是哪一個線程,也許我們需要喚醒的線程不能夠被喚醒,因此在實際使用時,一般都用notifyAll()方法,喚醒有所線程),線程被喚醒后會進入鎖池,等待獲取鎖標記。
------------------------------------------------------------------------------
以上是看的資料,IO的阻塞相當於是sleep,雖然能停止但不釋放資源。NIO采用IO multiplexing(IO多路復用)。(底層原理有待了解)。
sleep和wait都是使線程暫時停止執行的方法,但它們有很大的不同,sleep是線程類Thread 的方法,它是使當前線程暫時睡眠,可以放在任何位置。
而wait是Object類的方法,它是使當前線程暫時放棄對象的使用權進行等待,必須放在同步方法或同步塊里。
Sleep使用的時候,線程並不會放棄對象的使用權,即不會釋放對象鎖,所以在同步方法或同步塊中使用sleep,一個線程訪問時,其他的線程也是無法訪問的。
而wait是會釋放對象鎖的,就是當前線程放棄對象的使用權,讓其他的線程可以訪問。線程執行wait方法時,需要另一個線程調用notify進行喚醒。
而sleep只是暫時休眠一定時間,時間到了之后,自動恢復運行,不需另外的線程喚醒。
最簡單的解釋:
Wait()是等待別人釋放資源
Sleep()是自己占用資源,去做等待