一 cpu個數、核數、線程數的關系
cpu個數:是指物理上,也及硬件上的核心數;
核數:是邏輯上的,簡單理解為邏輯上模擬出的核心數;一個CPU核心數模擬出2線程的CPU
線程數:是同一時刻設備能並行執行的程序個數,線程數=cpu個數 * 核數,及程數=cpu個數(2) * 核數(2)=4
Windows: wmic 然后 物理CPU數 “cpu get NumberOfCores”, CPU核心數 “cpu get NumberOfLogicalProcessors”
Linux:
查看CPU個數 cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
查看核數 cat /proc/cpuinfo| grep "cpu cores"| uniq
Windows也可以查看任務管理器:
二 cpu線程數和Java多線程
(1) 線程是CPU級別的,單個線程同時只能在單個cpu線程中執行
(2) Java多線程並不是由於cpu線程數為多個才稱為多線程,當Java線程數大於cpu線程數,操作系統使用時間片機制,采用線程調度算法,頻繁的進行線程切換。
(3) 線程是操作系統最小的調度單位,進程是資源(比如:內存)分配的最小單位
(4)Java中的所有線程在JVM進程中,CPU調度的是進程中的線程
線程的調度是指按照特定的機制為多個線程分配CPU的使用權。有兩種調度模型:分時調度模型和搶占式調度模型
- 分時調度模型是指讓所有線程輪流獲得CPU的使用權,並且平均分配每個線程占用CPU的時間片。
- Java虛擬機采用搶占式調度模型,是指優先讓可運行池中處於就緒態的線程中優先級高的占用CPU,如果可運行池中線程的優先級相同,那么就隨機選擇一個線程,使其占用CPU,處於運行狀態的線程會一直執行,直至它不得不放棄CPU,一個線程會因為以下原因放棄CPU:
- (1)Java虛擬機讓當前線程暫時放棄CPU,轉到就緒態,使其他線程獲得運行機會
- (2)當前線程因為某些原因而處於阻塞狀態
- (3)線程運行結束
Java線程讓步:
3. Thread.yield()方法
就是說當一個線程使用了這個方法之后,它就會把自己CPU執行的時間讓掉,讓自己或者其它的線程運行,注意是讓自己或者其他線程運行(根據CPU的調度),並不是單純的讓給其他線程。
4.等待其他線程結束:join()
當前運行的線程可以調用另一個線程的join()方法,當前運行的線程將轉到阻塞狀態,直至另一個線程運行結束,它才會恢復運行(阻塞恢復到就緒)
知乎相關問題:
鏈接:https://www.zhihu.com/question/64072646/answer/216184631
Java語言的線程,從規范的角度來說是不強制要求任何具體的實現方式的。采用1:1、N:1、M:N模型都可以。先放個傳送門:RednaxelaFX:JVM中的線程模型是用戶級的么?
具體到我們平時常用的JVM實現,Oracle/Sun的HotSpot VM,它是用1:1模型來實現Java線程的,也就是說一個Java線程是直接通過一個OS線程來實現的,中間並沒有額外的間接結構。而且HotSpot VM自己也不干涉線程的調度,全權交給底下的OS去處理。所以如果OS想把某個線程調度到某個CPU/核上,它就自己弄了。
這個意義上說Java程序跑在HotSpot VM上開多個Java線程,就跟一個C/C++程序開了多線程來跑沒有任何兩樣。那么怎么控制這些線程分布到不同的CPU核上去呢?
在Linux上的話,可以用taskset來把線程綁在某個指定的核上。在Java層面上,有大大寫了個現成的庫來利用taskset綁核:OpenHFT/Java-Thread-Affinity 有興趣的話可以參考一下。
結束前提一下:JVM的實現有很多種,並不是所有JVM都像HotSpot VM這樣總是用1:1模型的。前面的傳送門已經有例子了所以這里就不多說,但還是想特別提一下免得給初學者留下“Java線程就肯定是OS線程”的誤解。請務必針對實現來討論這種問題。
參考:https://www.cnblogs.com/webglcn/p/10639065.html
https://zhuanlan.zhihu.com/p/86855590
在java里創建幾個線程怎么能確保他們跑在不同的CPU上?可以控制它們的分布嗎?