線程上下文切換:會存儲上一個執行線程的狀态,比如棧幀資訊,程式計數器資訊等,切換會耗費計算機資源的,是以并不是線程越多,執行效率就越高,如果線程數大于CPU的核心數,切換就會越頻繁
線程自己調用了sleep,yield,wait,join,park,synchronized,lock等方法,需要儲存線程狀态
重寫Thread的run()方法
将線程和線程要執行的東西分離,使用接口Runnable
用Future附加更多功能
Runnable,run()方法是void,是以沒有任何傳回結果
Callable位于java.util.concurrent包,call()方法能傳回結果
這兩者是沒有比較的,根本就是不同的東西,Runnable是線程執行的内容,Callalbe隻是說明該線程最後會傳回資料,而傳回的資料需要用Future去擷取
可以了解為,Callable和Future隻是增強了Runnable接口,Callable标記這個線程會有傳回,而Future就是去接收這個傳回
start()方法,啟動線程
run()方法,啟動的線程執行的操作,無傳回的Runnable和又傳回的Callable,Future最後都執行的是Runnable的run()方法
join()方法,等待線程運作結束,哪個線程調用join,哪個等待哪個線程結束,帶參數的等待,線程還沒結束,則繼續後面的代碼,如果線程提前結束,則join會提前結束
interrupt(),标記打斷狀态
static interrupted(),判斷目前線程是否被打斷,會清除打斷标記
isInterrupted(),判斷目前線程是否被打斷,不會清除打斷标記
yield(),讓出線程的使用權
調用該方法并不會打斷線程,隻是會标記該線程是否打斷
打斷阻塞的線程:調用sleep,wait,join的線程會進入阻塞狀态,打斷阻塞的線程,會清除打斷标記,也就是isInterupted為false,會抛出異常(InterruptedException)
打斷正常的線程,清除标記設定為true
打斷park線程,LockSupport.park()會讓線程進入park線程,打斷标記為true時,調用LockSupport.park()不會進入park狀态
雖然調用了interrupt()方法,t1,t2,t3線程依然會繼續執行,該方法做的事僅僅是設定打斷标記,設定成功與否還要分情況,并不會真正停止線程,而是要求線程自己去判斷是否需要停止,這麼做的理由和stop()方法一樣,如果是外部線程能終止一個線程,可能導緻終止的線程鎖死共享資源永遠不會釋放,是以隻是設定打斷标記,然後由線程自己去監控是否終止線程,就是兩階段終止模式。
stop()會真正的終止線程,如果此線程鎖住了共享資源,則永遠不會釋放鎖了,是以最好不要使用這個API,使用兩階段終止模式,讓線程自己終止線程。
作業系統的概念:初始,可運作,運作,阻塞,終止,作業系統将線程分為這5個狀态
java中的狀态:NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED,java中定義了6中狀态(java.lang.Thread.State)
NEW,建立了線程,但未啟動
RUNNABLE,其他狀态以外的狀态,比如等待IO,在作業系統看屬于阻塞,在java看屬于RUNNABLE狀态
BLOCKED,等待鎖的狀态
WAITING,等待其他線程,比如join,park,wait
TIMED_WAITING,等待其他線程,隻是有時間限制,比如sleep,join(1000),wait(1000)
TERMINATED,線程結束
經過測試,線程處于RUNNABLE和BLOCKED狀态的時候,執行interrupt()方法會将設定打斷标記為true,其他時候不會設定
沒有其他線程運作的時候,守護線程就會結束。
雖然t1線程是死循環,但它是一個守護線程,當t2線程結束的時候,t1也會結束。
能鎖住對象,隻能是對象,也就是在堆中有空間。synchronized修飾方法時,鎖住的是this對象。
線程安全的類。共享資源的對象化。
線程安全的類就是這麼提出來的,像String, StringBuffer, Vector, Hashtable就是線程安全的類。