一、并行與并發(fā)
并發(fā):任務交替執(zhí)行,看起像在同時進行。
并行:任務同時進行。
二、線程與進程
進程是操作系統(tǒng)分配資源的最小單位,進程與進程之間是相互獨立的;
線程是CPU調度的最小單位,一個進程可以有多個線程;
同進程的線程可以共享進程的大部分資源,線程自身也擁有一點自己的資源,比如程序計數(shù)器、棧等。
三、CPU與線程
CPU核數(shù)與線程數(shù):理論上是1:1的關系比較好;但是超核技術讓CPU可以與線程達到1:2的關系。
CPU時間片輪轉機制:CPU調度線程,是交替執(zhí)行,也就是說是并發(fā)的。CPU將調度時間分片,每個線程輪流獲得時間片,這讓線程看起來是并行的,實際是并發(fā)執(zhí)行。
CPU時間片輪轉機制比較關鍵的問題是時間分片的長度,時間片太長會導致有些線程有明顯卡頓感;時間片太短會大大浪費CPU切換所需要的時間。一般為200ms比較合適。
四、線程的方法
start():讓線程處于就緒狀態(tài),等待CPU時間片,執(zhí)行start()方法,run()才是真正在線程中.
run():一般不能主動調用,只能重寫,實現(xiàn)業(yè)務邏輯。
suspend():暫停,過期方法,不建議使用,因為暫停不會釋放鎖等操作,容易導致死鎖,不安全;
resume():繼續(xù),和suspend()一樣,不建議使用
stop():停止,過期方法,不建議使用,不釋放鎖,容易導致死鎖,不安全。
interrupt():設置中斷標記,實際是否中斷由代碼邏輯檢測中斷標記控制;
isInterrupted():判斷是否被中斷
Thread.interrupted():判斷是否被中斷,并且將中斷標記置為false
yield(): 讓出CPU資源,但不釋放鎖,所以執(zhí)行完之后可能繼續(xù)奪取CPU資源
join(): B線程中,調用A線程的join(),B線程將掛起,直到A線程執(zhí)行完才執(zhí)行B線程
setPriority(int):設置線程優(yōu)先級,0-10,一般為5,越大則分配的時機片越多,但不一定。
setDaemon(true):設置為守護線程,主線程退出以后,守護線程自動退出,比如垃圾回收線程
注意:wait()、notify()是Object類的方法。
yield() 、sleep()被調用后,都不會釋放當前線程所持有的鎖。調用wait()方法后,會釋放當前線程持有的鎖,而且當前被喚醒后,會重新去競爭鎖,鎖競爭到后才會執(zhí)行wait 方法后面的代碼。調用notify()系列方法后,對鎖無影響,線程只有在syn 同步代碼執(zhí)行完后才會自然而然的釋放鎖,所以notify()系列方法一般都是syn 同步代碼的最后一行。wait()和notify()務必在synchronized代碼塊中使用。
wait()、notify()配合使用,可以實現(xiàn)線程間協(xié)作。
線程A在synchronized代碼塊中執(zhí)行對象O的wait(),釋放鎖,進入等待,線程B獲得鎖,執(zhí)行邏輯,通過對象O的notify()通知線程A執(zhí)行wait()之后的代碼。
五、線程的狀態(tài)
Java中線程的狀態(tài)分為6種:
- 初始:新創(chuàng)建了一個線程對象,但還沒有調用start()方法。
- 運行:Java線程中將就緒(ready)和運行中(running)兩種狀態(tài)籠統(tǒng)的稱為“運行”。
線程對象創(chuàng)建后,其他線程(比如main線程)調用了該對象的start()方法。該狀態(tài)的線程位于可運行線程池中,等待被線程調度選中,獲取CPU的使用權,此時處于就緒狀態(tài)(ready)。就緒狀態(tài)的線程在獲得CPU時間片后變?yōu)檫\行中狀態(tài)(running)。 - 阻塞:表示線程阻塞于鎖。
- 等待:進入該狀態(tài)的線程需要等待其他線程做出一些特定動作(通知或中斷)。
- 超時等待:該狀態(tài)不同于WAITING,它可以在指定的時間后自行返回。
- 終止:表示該線程已經執(zhí)行完畢。