首頁 > 軟體

Java之程序和執行緒的區別

2023-03-29 06:02:34

程序和執行緒

程序

一個在記憶體中執行的應用程式。每個程序都有自己獨立的一塊記憶體空間,一個程序可以有多個執行緒,比如在Windows系統中,一個執行的xx.exe就是一個程序。

執行緒

程序中的一個執行任務(控制單元),負責當前程序中程式的執行。一個程序至少有一個執行緒,一個程序可以執行多個執行緒,多個執行緒可共用資料。

與程序不同的是同類的多個執行緒共用程序的堆和方法區資源,但每個執行緒有自己的程式計數器、虛擬機器器棧和本地方法棧,所以系統在產生一個執行緒,或是在各個執行緒之間作切換工作時,負擔要比程序小得多,也正因為如此,執行緒也被稱為輕量級程序。

Java 程式天生就是多執行緒程式,我們可以通過 JMX 來看一下一個普通的 Java 程式有哪些執行緒,程式碼如下。

public class MultiThread {
	public static void main(String[] args) {
		// 獲取 Java 執行緒管理 MXBean
		ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
		// 不需要獲取同步的 monitor 和 synchronizer 資訊,僅獲取執行緒和執行緒堆疊資訊
		ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
		// 遍歷執行緒資訊,僅列印執行緒 ID 和執行緒名稱資訊
		for (ThreadInfo threadInfo : threadInfos) {
			System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName());
		}
	}
}

上述程式輸出如下(輸出內容可能不同,不用太糾結下面每個執行緒的作用,只用知道 main 執行緒執行 main 方法即可):

[6] Monitor Ctrl-Break //監聽執行緒轉儲或「執行緒堆疊跟蹤」的執行緒
[5] Attach Listener //負責接收到外部的命令,而對該命令進行執行的並且把結果返回給傳送者
[4] Signal Dispatcher // 分發處理給 JVM 訊號的執行緒
[3] Finalizer //在垃圾收集前,呼叫物件 finalize 方法的執行緒
[2] Reference Handler //用於處理參照物件本身(軟參照、弱參照、虛參照)的垃圾回收的執行緒
[1] main //main 執行緒,程式入口

從上面的輸出內容可以看出:一個 Java 程式的執行是 main 執行緒和多個其他執行緒同時執行。

程序與執行緒的區別總結

執行緒具有許多傳統程序所具有的特徵,故又稱為輕型程序(Light—Weight Process)或程序元;而把傳統的程序稱為重型程序(Heavy—Weight Process),它相當於只有一個執行緒的任務。在引入了執行緒的作業系統中,通常一個程序都有若干個執行緒,至少包含一個執行緒。

根本區別:程序是作業系統資源分配的基本單位,而執行緒是處理器任務排程和執行的基本單位

資源開銷:每個程序都有獨立的程式碼和資料空間(程式上下文),程式之間的切換會有較大的開銷;執行緒可以看做輕量級的程序,同一類執行緒共用程式碼和資料空間,每個執行緒都有自己獨立的執行棧和程式計數器(PC),執行緒之間切換的開銷小。

包含關係:如果一個程序內有多個執行緒,則執行過程不是一條線的,而是多條線(執行緒)共同完成的;執行緒是程序的一部分,所以執行緒也被稱為輕權程序或者輕量級程序。

記憶體分配:同一程序的執行緒共用本程序的地址空間和資源,而程序之間的地址空間和資源是相互獨立的

影響關係:一個程序崩潰後,在保護模式下不會對其他程序產生影響,但是一個執行緒崩潰整個程序都死掉。所以多程序要比多執行緒健壯。

執行過程:每個獨立的程序有程式執行的入口、順序執行序列和程式出口。但是執行緒不能獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制,兩者均可並行執行

從 JVM 角度說程序和執行緒之間的關係(重要)

圖解程序和執行緒的關係

下圖是 Java 記憶體區域,通過下圖我們從 JVM 的角度來說一下執行緒和程序之間的關係。

從上圖可以看出:一個程序中可以有多個執行緒,多個執行緒共用程序的方法區 (JDK1.8 之後的元空間)資源,但是每個執行緒有自己的程式計數器、虛擬機器器棧 和 本地方法棧。

程式計數器為什麼是私有的?

程式計數器主要有下面兩個作用:

1. 位元組碼直譯器通過改變程式計數器來依次讀取指令,從而實現程式碼的流程控制,如:順序執行、選擇、迴圈、例外處理。
2. 在多執行緒的情況下,程式計數器用於記錄當前執行緒執行的位置,從而當執行緒被切換回來的時候能夠知道該執行緒上次執行到哪兒了。

需要注意的是,如果執行的是 native 方法,那麼程式計數器記錄的是 undefined 地址,只有執行的是 Java 程式碼時程式計數器記錄的才是下一條指令的地址。

所以,程式計數器私有主要是為了執行緒切換後能恢復到正確的執行位置。

虛擬機器器棧和本地方法棧為什麼是私有的?

  • 虛擬機器器棧:每個 Java 方法在執行的同時會建立一個棧幀用於儲存區域性變數表、運算元棧、常數池參照等資訊。從方法呼叫直至執行完成的過程,就對應著一個棧幀在 Java 虛擬機器器棧中入棧和出棧的過程。
  • 本地方法棧:和虛擬機器器棧所發揮的作用非常相似,區別是: 虛擬機器器棧為虛擬機器器執行 Java 方法 (也就是位元組碼)服務,而本地方法棧則為虛擬機器器使用到的 Native 方法服務。 在 HotSpot 虛擬機器器中和 Java 虛擬機器器棧合二為一。

所以,為了保證執行緒中的區域性變數不被別的執行緒存取到,虛擬機器器棧和本地方法棧是執行緒私有的。

一句話簡單瞭解堆和方法區

堆和方法區是所有執行緒共用的資源,其中堆是程序中最大的一塊記憶體,主要用於存放新建立的物件 (所有物件都在這裡分配記憶體),方法區主要用於存放已被載入的類資訊、常數、靜態變數、即時編譯器編譯後的程式碼等資料。

多程序和多執行緒區別

多程序:作業系統中同時執行的多個程式

多執行緒:在同一個程序中同時執行的多個任務

舉個例子,多執行緒下載軟體,可以同時執行多個執行緒,但是通過程式執行的結果發現,每一次結果都不一致。 因為多執行緒存在一個特性:隨機性。造成的原因:CPU在瞬間不斷切換去處理各個執行緒而導致的,可以理解成多個執行緒在搶CPU資源。

多執行緒提高CPU使用率

多執行緒並不能提高執行速度,但可以提高執行效率,讓CPU的使用率更高。但是如果多執行緒有安全問題或出現頻繁的上下文切換時,運算速度可能反而更低。

Java中的多執行緒

Java程式的程序裡有幾個執行緒:主執行緒,垃圾回收執行緒(後臺執行緒)等

在 Java 中,當我們啟動 main 函數時其實就是啟動了一個 JVM 的程序,而 main 函數所在的執行緒就是這個程序中的一個執行緒,也稱主執行緒。

Java支援多執行緒,當Java程式執行main方法的時候,就是在執行一個名字叫做main的執行緒,可以在main方法執行時,開啟多個執行緒A,B,C,多個執行緒 main,A,B,C同時執行,相互搶奪CPU,Thread類是java.lang包下的一個常用類,每一個Thread類的物件,就代表一個處於某種狀態的執行緒

到此這篇關於Java之程序和執行緒的區別的文章就介紹到這了,更多相關程序與執行緒的區別內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com