解析Java的多線程機制(1)(轉)
解析Java的多線程機制(1)(轉)[@more@]進程與應用程序的區別
進程(Process)是最初定義在Unix等多用戶、多任務操作系統環境下用于表示應用程序在內存環境中基本執行單元的概念。以Unix操作系統為例,進程是Unix操作系統環境中的基本成分、是系統資源分配的基本單位。Unix操作系統中完成的幾乎所有用戶管理和資源分配等工作都是通過操作系統對應用程序進程的控制來實現的。
C、C++、Java等語言編寫的源程序經相應的編譯器編譯成可執行文件后,提交給計算機處理器運行。這時,處在可執行狀態中的應用程序稱為進程。從用戶角度來看,進程是應用程序的一個執行過程。從操作系統核心角度來看,進程代表的是操作系統分配的內存、CPU時間片等資源的基本單位,是為正在運行的程序提供的運行環境。進程與應用程序的區別在于應用程序作為一個靜態文件存儲在計算機系統的硬盤等存儲空間中,而進程則是處于動態條件下由操作系統維護的系統資源管理實體。多任務環境下應用程序進程的主要特點包括:
●進程在執行過程中有內存單元的初始入口點,并且進程存活過程中始終擁有獨立的內存地址空間;
●進程的生存期狀態包括創建、就緒、運行、阻塞和死亡等類型;
●從應用程序進程在執行過程中向CPU發出的運行指令形式不同,可以將進程的狀態分為用戶態和核心態。處于用戶態下的進程執行的是應用程序指令、處于核心態下的應用程序進程執行的是操作系統指令。
在Unix操作系統啟動過程中,系統自動創建swapper、init等系統進程,用于管理內存資源以及對用戶進程進行調度等。在Unix環境下無論是由操作系統創建的進程還要由應用程序執行創建的進程,均擁有唯一的進程標識(PID)。
進程與Java線程的區別
應用程序在執行過程中存在一個內存空間的初始入口點地址、一個程序執行過程中的代碼執行序列以及用于標識進程結束的內存出口點地址,在進程執行過程中的每一時間點均有唯一的處理器指令與內存單元地址相對應。
Java語言中定義的線程(Thread)同樣包括一個內存入口點地址、一個出口點地址以及能夠順序執行的代碼序列。但是進程與線程的重要區別在于線程不能夠單獨執行,它必須運行在處于活動狀態的應用程序進程中,因此可以定義線程是程序內部的具有并發性的順序代碼流。
Unix操作系統和Microsoft Windows操作系統支持多用戶、多進程的并發執行,而Java語言支持應用程序進程內部的多個執行線程的并發執行。多線程的意義在于一個應用程序的多個邏輯單元可以并發地執行。但是多線程并不意味著多個用戶進程在執行,操作系統也不把每個線程作為獨立的進程來分配獨立的系統資源。進程可以創建其子進程,子進程與父進程擁有不同的可執行代碼和數據內存空間。而在用于代表應用程序的進程中多個線程共享數據內存空間,但保持每個線程擁有獨立的執行堆棧和程序執行上下文(Context)。
基于上述區別,線程也可以稱為輕型進程 (Light Weight Process,LWP)。不同線程間允許任務協作和數據交換,使得在計算機系統資源消耗等方面非常廉價。
線程需要操作系統的支持,不是所有類型的計算機都支持多線程應用程序。Java程序設計語言將線程支持與語言運行環境結合在一起,提供了多任務并發執行的能力。這就好比一個人在處理家務的過程中,將衣服放到洗衣機中自動洗滌后將大米放在電飯鍋里,然后開始做菜。等菜做好了,飯熟了同時衣服也洗好了。
需要注意的是:在應用程序中使用多線程不會增加 CPU 的數據處理能力。只有在多CPU 的計算機或者在網絡計算體系結構下,將Java程序劃分為多個并發執行線程后,同時啟動多個線程運行,使不同的線程運行在基于不同處理器的Java虛擬機中,才能提高應用程序的執行效率。
另外,如果應用程序必須等待網絡連接或數據庫連接等數據吞吐速度相對較慢的資源時,多線程應用程序是非常有利的。基于Internet的應用程序有必要是多線程類型的,例如,當開發要支持大量客戶機的
服務器端應用程序時,可以將應用程序創建成多線程形式來響應客戶端的連接請求,使每個連接用戶獨占一個客戶端連接線程。這樣,用戶感覺服務器只為連接用戶自己服務,從而縮短了服務器的客戶端響應時間。
Java語言的多線程程序設計方法
利用Java語言實現多線程應用程序的方法很簡單。根據多線程應用程序繼承或實現對象的不同可以采用兩種方式:一種是應用程序的并發運行對象直接繼承Java的線程類Thread;另外一種方式是定義并發執行對象實現Runnable接口。
繼承Thread類的多線程程序設計方法
Thread 類是JDK中定義的用于控制線程對象的類,在該類中封裝了用于進行線程控制的方法。見下面的示例代碼:
//Consumer.java
import java.util.*;
class Consumer extends Thread
{
int nTime;
String strConsumer;
public Consumer(int nTime, String strConsumer)
{
this.nTime = nTime;
this.strConsumer = strConsumer;
}
public void run()
{
while(true)
{
try
{
System.out.println("Consumer name:"+strConsumer+"
");
Thread.sleep(nTime);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
static public void main(String args[])
{
Consumer aConsumer = new Consumer (1000, "aConsumer");
aConsumer.start();
Consumer bConsumer = new Consumer (2000, "bConsumer");
bConsumer.start();
Consumer cConsumer = new Consumer (3000, "cConsumer ");
cConsumer.start();
}
}
從上面的程序代碼可以看出:多線程執行地下Consumer繼承Java語言中的線程類Thread并且在main方法中創建了三個 Consumer對象的實例。當調用對象實例的start方法時,自動調用Consumer類中定義的run方法啟動對象線程運行。線程運行的結果是每間隔nTime時間打印出對象實例中的字符串成員變量strConsumer的內容。
可以總結出繼承Thread類的多線程程序設計方法是使應用程序類繼承Thread類并且在該類的run方法中實現并發性處理過程。