線程原理學習筆記

1、線程的實現方式

(1)使用內核線程實現

(2)使用用戶線程實現

(3)使用用戶線程加輕量級進程混合實現

1、1 內核線程

直接由操作系統內核支持的線程,這種線程由內核來完成線程切換,內核通過操縱調度器對線程進行調度,並負責將線程的任務映射到各個處理器上。每個內核線程可以視為內核的一個分身,這樣操作系統就有能力同時處理多件事情,支持多線程的內核就叫做多線程內核

由於內核線程的支持,每個輕量級進程都成為一個獨立的調度單元,即使有一個輕量級進程在系統調用中阻塞了,也不會影響整個進程繼續工作,但是輕量級進程具有它的侷限性:

(1)首先,由於是基於內核線程實現的,所以各種線程操作,都需要進行系統調用,而系統調用的代價相對較高。

(2)每個輕量級進程都需要有一個內核線程的支持,因此輕量級進程要消耗一定的內核資源,因此一個系統支持輕量級進程的數量是有限的。

1.2、用戶線程

從廣義上講,一個線程只要不是內核線程,就可以認為是用戶線程

狹義上的用戶線程指的是完全建立在用戶空間的線程庫上,系統內核不能感知線程存在的實現。這種線程不需要切換到內核態,因此操作可以是非常快速且低消耗的,也可以支持規模更大的線程數量。 使用用戶線程的優勢在於不需要系統內核支援,劣勢也在於沒有系統內核的支援,所有的線程操作都需要用戶程序自己處理。線程的創建、切換和調度都是需要考慮的問題,因而使用用戶線程實現的程序一般都比較複雜

1.3 用戶線程加輕量級進程混合實現

在這種混合實現下,既存在用戶線程,也存在輕量級進程。用戶線程還是完全建立在用戶空間中,因此用戶線程的創建,切換,析構等操作依然廉價,並且可以支持大規模用戶線程併發。而操作系統提供支持的輕量級進程則作為用戶線程和內核線程之間的橋樑,這樣可以使用內核提供的線程調度功能及處理器映射,並且用戶線程的系統調用要通過輕量級線程來完成,大大降低了整個進程被完全阻塞的風險

2、java線程的實現

JAVA線程現在的實現是基於操作系統原生線程模型來實現的。因此,現在操作系統支持怎樣的線程模型,在很大程度上決定了JAVA虛擬機的線程是怎樣映射的。這點在不同的平臺上沒有辦法達成一致

2.1 java線程調度

線程調度的方式有協同式線程調度和搶佔式線程調度

協同式線程調度:線程的執行時間由線程本身控制,線程把自己的工作執行完了以後,要主動通知系統切換到另外一個線程上

搶佔式調度:每個線程都將由系統來分配執行時間,線程的切換不由線程本身來決定。因此線程的執行時間是可控的,也不會因為一個線程導致整個進行阻塞

雖然Java線程是通過系統調度自動完成的,但我們可以”建議“系統給某些線程多分配一點執行時間,另外一些線程則少分配一點——此操作可以通過設置線程優先級來完成

Thread.MAX_PRIORITY; //最高優先級 10

Thread.NORM_PRIORITY; // 默認優先級 5

Thread.MIN_PRIORITY; // 最低優先級 1

2.2 線程狀態

Java定義了6種線程狀態,在任意一個時間點,一個線程只能有且只有其中一種狀態

新建(NEW):創建後尚未啟動的線程處於這種狀態。(為start)

運行(Runable):Runable包括了操作系統線程狀態中的Running和Ready,也就是處於此狀態的線程有可能正在執行,也有可能正在等待著CPU為它分配執行時間

無限期等待(Waiting):處於這種狀態的線程不會被分配CPU執行時間,它們要等待被其他線程顯式地喚醒

  • 沒有設置Timeout參數的Object.wait()方法;
  • 沒有設置Timeout參數的Thread.join()方法;
  • LockSupport.park()方法;

限期等待(Timed Waiting):處於這種狀態的線程也不會被分配CPU執行時間,不過無須等待被其他線程顯式地喚醒,在一定時間之後它們會由系統自動喚醒

  • Thread.sleep()方法;
  • 設置了Timeout參數的Object.wait()方法;
  • 設置了Timeout參數的Thread.join()方法;

阻塞(Blocked):線程被阻塞了,“阻塞狀態”與”等待狀態“的區別是:”阻塞狀態“在等待獲取一個排它鎖,這個事件將在另外一個線程放棄這個鎖的時候發生;而”等待狀態“則是在等待一段時間,或者喚醒動作的發生。

  • 在程序等待進入同步區域的時候,線程將進入這種狀態

結束(Terminated):已終止線程狀態,線程已經結束運行

學習筆記,如有侵權聯繫刪除,如果錯誤,請留言討論


分享到:


相關文章: