您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關怎樣實現Java線程的深入探討,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
1.什么是線程
一般來說,我們把正在計算機中執行的程序叫做"進程"(Process) ,而不將其
稱為程序(Program)。所謂"線程"(Thread),是"進程"中某個單一順序的控制流。
新興的操作系統,如Mac,windows NT,Windows 95等,大多采用多線程的概念,把線
程視為基本執行單位。線程也是Java中的相當重要的組成部分之一。
甚至最簡單的Applet也是由多個線程來完成的。在Java中,任何一個Applet的
paint()和update()方法都是由AWT(Abstract Window Toolkit)繪圖與事件處理線
程調用的,而Applet 主要的里程碑方法——init(),start(),stop()和destory()
——是由執行該Applet的應用調用的。
單線程的概念沒有什么新的地方,真正有趣的是在一個程序中同時使用多個線
程來完成不同的任務。某些地方用輕量進程(Lightweig ht Process)來代替線程
,線程與真正進程的相似性在于它們都是單一順序控制流。然而線程被認為輕量是
由于它運行于整個程序的上下文內,能使用整個程序共有的資源和程序環境。
作為單一順序控制流,在運行的程序內線程必須擁有一些資源作為必要的開銷
。例如,必須有執行堆棧和程序計數器。在線程內執行的代碼只在它的上下文中起
作用,因此某些地方用"執行上下文"來代替"線程"。
2.線程屬性
為了正確有效地使用線程,必須理解線程的各個方面并了解Java 實時系統。
必須知道如何提供線程體、線程的生命周期、實時系統如 何調度線程、線程組、
什么是幽靈線程(Demo nThread)。
(1)線程體
所有的操作都發生在線程體中,在Java中線程體是從Thread類繼承的run()方
法,或實現Runnable接口的類中的run()方法。當線程產生并初始化后,實時系統調
用它的run()方法。run()方法內的代碼實現所產生線程的行為,它是線程的主要部
分。
(2)線程狀態
附圖表示了線程在它的生命周期內的任何時刻所能處的狀態以及引起狀態改
變的方法。這圖并不是完整的有限狀態圖,但基本概括了線程中比較感興趣和普遍
的方面。以下討論有關線程生命周期以此為據。
●新線程態(New Thread)
產生一個Thread對象就生成一個新線程。當線程處于"新線程"狀態時,僅僅是
一個空線程對象,它還沒有分配到系統資源。因此只能啟動或終止它。任何其他操
作都會引發異常。
●可運行態(Runnable)
start()方法產生運行線程所必須的資源,調度線程執行,并且調用線程的run
()方法。在這時線程處于可運行態。該狀態不稱為運行態是因為這時的線程并不
總是一直占用處理機。特別是對于只有一個處理機的PC而言,任何時刻只能有一個
處于可運行態的線程占用處理 機。Java通過調度來實現多線程對處理機的共享。
●非運行態(Not Runnable)
當以下事件發生時,線程進入非運行態。
①suspend()方法被調用;
②sleep()方法被調用;
③線程使用wait()來等待條件變量;
④線程處于I/O等待。
●死亡態(Dead)
當run()方法返回,或別的線程調用stop()方法,線程進入死亡態 。通常Appl
et使用它的stop()方法來終止它產生的所有線程。
(3)線程優先級
雖然我們說線程是并發運行的。然而事實常常并非如此。正如前面談到的,當
系統中只有一個cpu時,以某種順序在單CPU情況下執行多線程被稱為調度(schedu
ling)。Java采用的是一種簡單、固定的調度法,即固定優先級調度。這種算法是
根據處于可運行態線程的相對優先級來實行調度。當線程產生時,它繼承原線程的
優先級。在需要時可對優先級進行修改。在任何時刻,如果有多條線程等待運行,
系統選擇優先級最高的可運行線程運行。只有當它停止、自動放棄、或由于某種
原因成為非運行態低優先級的線程才能運行。如果兩個線程具有相同的優先級,它
們將被交替地運行。
Java實時系統的線程調度算法還是強制性的,在任何時刻,如果一個比其他線
程優先級都高的線程的狀態變為可運行態,實時系統將選擇該線程來運行。
(4)幽靈線程
任何一個Java線程都能成為幽靈線程。它是作為運行于同一個進程內的對象
和線程的服務提供者。例如,HotJava瀏覽器有一個稱為" 后臺圖片閱讀器"的幽靈
線程,它為需要圖片的對象和線程從文件系統或網絡讀入圖片。
幽靈線程是應用中典型的獨立線程。它為同一應用中的其他對象和線程提供
服務。幽靈線程的run()方法一般都是無限循環,等待服務請求。
(5)線程組
每個Java線程都是某個線程組的成員。線程組提供一種機制,使得多個線程集
于一個對象內,能對它們實行整體操作。譬如,你能用一個方法調用來啟動或掛起
組內的所有線程。Java線程組由ThreadGroup類實現。
當線程產生時,可以指定線程組或由實時系統將其放入某個缺省的線程組內。
線程只能屬于一個線程組,并且當線程產生后不能改變它所屬的線程組。
3.多線程程序
對于多線程的好處這就不多說了。但是,它同樣也帶來了某些新的麻煩。只要
在設計程序時特別小心留意,克服這些麻煩并不算太困難。
(1)同步線程
許多線程在執行中必須考慮與其他線程之間共享數據或協調執行狀態。這就
需要同步機制。在Java中每個對象都有一把鎖與之對應。但Java不提供單獨的lo
ck和unlock操作。它由高層的結構隱式實現, 來保證操作的對應。(然而,我們注
意到Java虛擬機提供單獨的monito renter和monitorexit指令來實現lock和unlo
ck操作。)
synchronized語句計算一個對象引用,試圖對該對象完成鎖操作, 并且在完成
鎖操作前停止處理。當鎖操作完成synchronized語句體得到執行。當語句體執行
完畢(無論正常或異常),解鎖操作自動完成。作為面向對象的語言,synchronized
經常與方法連用。一種比較好的辦法是,如果某個變量由一個線程賦值并由別的線
程引用或賦值,那么所有對該變量的訪問都必須在某個synchromized語句或synch
ronized方法內。
現在假設一種情況:線程1與線程2都要訪問某個數據區,并且要求線程1的訪
問先于線程2, 則這時僅用synchronized是不能解決問題的。這在unix或Windows
NT中可用Simaphore來實現。而Java并不提供。在Java中提供的是wait()和noti
fy()機制。使用如下:
synchronized method-1(…){ call by thread 1.
∥access data area;
available=true;
notify()
}
synchronized method-2(…){∥call by thread 2.
while(!available)
try{
wait();∥wait for notify().
}catch (Interrupted Exception e){
}
∥access data area
}
其中available是類成員變量,置初值為false。
如果在method-2中檢查available為假,則調用wait()。wait()的作用是使線
程2進入非運行態,并且解鎖。在這種情況下,method-1可以被線程1調用。當執行
notify()后。線程2由非運行態轉變為可運行態。當method-1調用返回后。線程2
可重新對該對象加鎖,加鎖成功后執行wait()返回后的指令。這種機制也能適用于
其他更復雜的情況。
(2)死鎖
如果程序中有幾個競爭資源的并發線程,那么保證均衡是很重要的。系統均衡
是指每個線程在執行過程中都能充分訪問有限的資源。系統中沒有餓死和死鎖的
線程。Java并不提供對死鎖的檢測機制。對大多數的Java程序員來說防止死鎖是
一種較好的選擇。最簡單的防止死鎖的方法是對競爭的資源引入序號,如果一個線
程需要幾個資源,那么它必須先得到小序號的資源,再申請大序號的資源。
關于怎樣實現Java線程的深入探討就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。