首頁 >Java >java教程 >Java中執行緒如何實作? Java執行緒的實作方法(圖文)

Java中執行緒如何實作? Java執行緒的實作方法(圖文)

不言
不言原創
2018-09-17 15:18:242098瀏覽

本篇文章帶給大家的內容是關於Java中執行緒如何實現? Java線程的實作方法(圖文),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

進程與執行緒

在傳統的作業系統中,最核心的概念是“進程”,進程是對正在運行的程式的一個抽象。
進程的存在讓「並行」成為了可能,在一個作業系統中,允許運行著多個進程,這些進程「看起來」是同時在運行的。
如果我們的電腦同時運行著web 瀏覽器、電子郵件用戶端、即時通訊軟體例如QQ微信等多個進程,我們感覺這些進程都是同時在運行的,假設這台電腦搭配的是多個CPU 或多核心CPU,那麼這種多個進程並行的現象可能一點也不奇怪,完全可以為每個進程單獨分配一個CPU,這樣就實現了多進程並行。
然而事實上,在電腦只有一個 CPU 的情況下,它也能給人類一種感覺:多個進程同時在運作。但人類的感覺往往是比較模糊的,不精確的。事實是由於CPU 的運算速度非常地快,它能快速地在各個進程之間切換,在某一瞬間,CPU 只能運行一個進程,但一秒鐘之內,它就能透過快速切換,讓人產生多個進程同時在運作的錯覺。
在作業系統中,為什麼在行程的基礎上,又衍生出了執行緒的概念呢?

  1. 由於對於某些進程而言,它內部會發生多種活動,有些活動可能會在某個時間裡阻塞,有些活動不會,如果透過執行緒將這些活動分離開使它們能夠並行地運行,則設計程式的時候會更加簡單。

  2. 執行緒比進程的建立更加輕量級,效能消耗更少

  3. 如果一個行程既需要CPU 運算,也需要I/ O處理,擁有多執行緒允許這些活動重疊進行,加快整個行程的執行速度。

每一個進程在作業系統中都擁有獨立的一塊記憶體位址空間,該行程創建的所有執行緒共享這塊內存,支援多執行緒的作業系統,會讓執行緒作為CPU 調度的最小單位。 CPU 的時間片在不同的執行緒之間進行分配。

線程的可能實現方式

基本上主流的作業系統都支援線程,也提供了線程的實作。而 Java 語言為了因應不同硬體和作業系統的差異,提供了對執行緒操作的統一抽象,在 Java 中我們使用 Thread 類別來代表一個執行緒。
Thread 的具體實作可能會有不同的實作方式:

使用核心執行緒實作

核心執行緒是作業系統核心支援的線程,在核心中有一個線程表用來記錄系統中的所有線程,在創建或銷毀一個線程時,都需要涉及到系統調用,然後再內核中對線程表進行更新操作。對內核線程的阻塞以及其它操作,都涉及到系統調用,系統調用的代價都比較大,涉及到在用戶態和內核態之間的來回切換。此外,核心內部有執行緒調度器,用於決定應該將 CPU 時間片分配個哪個執行緒。
程式一般不會直接操作內核線程,而是使用內核線程的一種高級接口,輕量級進程。輕量級進程與核心執行緒之間的關係是 1:1,每一個輕量級進程內部都有一個核心執行緒支援。

Java中執行緒如何實作? Java執行緒的實作方法(圖文)

上圖中, LWP 指 Light Weight Process,即輕量級進程;KLT 指 Kernel Level Thread,即核心執行緒。

使用使用者執行緒實作

使用者執行緒是程式或程式語言自己實作的執行緒函式庫,系統核心無法感知到這些執行緒的存在。用戶線程的建立、同步、銷毀和調度,都在用戶態中完成,無須內核的幫助,不需要進行系統調用,這樣的好處是對於線程的操作是非常高效的。在這種情況下,進程和用戶執行緒的比例是 1 :N。

Java中執行緒如何實作? Java執行緒的實作方法(圖文)

當使用者狀態執行緒面對如何阻塞執行緒時,會面臨困難,阻塞一個使用者狀態執行緒會出現把整個行程都阻塞的情況,多線程也就失去了意義。因為缺少核心的支持,所以很多需要利用核心才能完成的工作,例如阻塞與喚醒執行緒、多 CPU 環境下執行緒的映射等,都需要使用者程式去實現,實現起來會異常困難。

使用使用者執行緒和核心執行緒混合實作

在這種混合實作下,既存在使用者線程,也存在核心線程。使用者態線程的建立、切換這些操作依然很高效,而且用戶態實現的線程,比較容易加大線程的規模。需要作業系統核心支援的功能,則透過核心執行緒來做到,例如映射到不同的處理器上、處理執行緒的阻塞與喚醒以及核心執行緒的調度等。這種實作仍然會使用到輕量級進程 LWP,它是用戶執行緒和核心執行緒之間的橋樑。

Java中執行緒如何實作? Java執行緒的實作方法(圖文)

Java 執行緒的實作

#在JDK1.2 之前, Java 的執行緒是使用使用者執行緒實作的,在JDK1. 2 之後,Java 才採用作業系統原生支援的執行緒模型來實現,Java 執行緒模型的實作方式,主要取決於作業系統。對於 Oracle JDK 來說,在 Windows 和 Linux 上的執行緒模型是採用一對一的方式實現的,即一條 Java 執行緒對應到一條輕量級進程(核心執行緒)。而在 Solaris 平台中,Java 則支援 1 :1 和 N : M 的執行緒模型。

執行緒的阻塞與等待

Java 中的執行緒的狀態有以下幾個:New,Runnable,Waiting, TimedWaiting, Blocked,Terminated。

Java中執行緒如何實作? Java執行緒的實作方法(圖文)

  • NEW:執行緒初步創建,未執行

  • RUNNABLE:執行緒正在運行,但不一定消耗CPU

  • BLOCKED:執行緒正在等待另一個執行緒釋放鎖定

  • WAITING:執行緒執行了wait, join , LockSupport.park() 方法

  • TIMED_WAITING:執行緒呼叫了sleep, wait, join, LockSupport.parkNanos() 等方法,與WAITING 狀態不同的是,這些方法帶有表示時間的參數。

其中Blocked 和Waiting 有個重要的差異是,阻塞(Blocked)狀態的執行緒在等待取得一個排他鎖,例如執行緒在等待進入一個synchronized關鍵字包圍的臨界區時,就進入Blocked 狀態。而 Waiting 狀態則是在等待被喚醒,或是等待一段時間。

#

以上是Java中執行緒如何實作? Java執行緒的實作方法(圖文)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn