一 什麼是線程
現代作業系統在運行一個程式時,會為其建立一個進程。例如,啟動一個Java程式,作業系統就會建立一個Java進程。線程概念是在進程基礎上定義的,線程是現代作業系統能夠調度的最小單元,它被包含在進程之中,是行程中的實際運作單位。 一條線程指的是進程中一個單一順序的控制流程,一個進程中可以並行多個線程,每條線程並存執行不同的任務。
一個Java程式從main( )方法開始執行,然後根據既定的代碼邏輯執行,看似沒有其他線程的參與,但實際上java程式天生就是多線程程式,因為執行main( )方法就是一個名稱為mian( )進程。一個最普通java程式,至少具備以下幾個線程:
public class Main { public static void main(String[] args) { ThreadGroup group = Thread.currentThread().getThreadGroup(); ThreadGroup topGroup = group; // 遍曆線程組樹,擷取根線程組 while (group != null) { topGroup = group; group = group.getParent(); } // 啟用的線程數再加一倍,防止枚舉時有可能剛好有動態線程產生 int slackSize = topGroup.activeCount() * 2; Thread[] slackThreads = new Thread[slackSize]; // 擷取根線程組下的所有線程,返回的actualSize便是最終的線程數 int actualSize = topGroup.enumerate(slackThreads); Thread[] atualThreads = new Thread[actualSize]; // 複製slackThreads中有效值到atualThreads System.arraycopy(slackThreads, 0, atualThreads, 0, actualSize); System.out.println("Threads size is " + atualThreads.length); for (Thread thread : atualThreads) { System.out.println(thread.getName()); } } }
列印結果:
Threads size is 5 Reference Handler //清除Reference的線程 Finalizer //調用對象difalize方法的介面 Signal Dispatcher //分發處理髮給JVM訊號的線程 main //main線程,使用者程式入口
二 為什麼使用多線程
使用多線程的理由之一是和進程相比,它是一種常花銷小,切換快,更”節儉”的多任務操作方式。在Linux系統下,啟動一個新的進程必須分配給它獨立的地址空間,建立眾多的資料表來維護它的程式碼片段、堆棧段和資料區段,這是一種”昂貴”的多任務工作方式。而運行於一個進程中的多個線程,它們彼此之間使用相同的地址空間,共用大部分資料,啟動一個線程所花費的空間遠遠小於啟動一個進程所花費的空間,而且,線程間彼此切換所需的時間也遠遠小於進程間切換所需要的時間。
使用多線程的理由之二是線程間方便的通訊機制。對不同進程來說,它們具有獨立的資料空間,要進行資料的傳遞只能通過通訊的方式進行,這種方式不僅費時,而且很不方便。線程則不然,由於同一進程下的線程之間共用資料空間,所以一個線程的資料可以直接為其它線程所用,這不僅快捷,而且方便。當然,資料的共用也帶來其他一些問題,有的變數不能同時被兩個線程所修改,有的子程式中聲明為static的資料更有可能給多線程程式帶來災難性的打擊,這些正是編寫多線程程式時最需要注意的地方。