明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

Java多線程程序設(shè)計(jì)-區(qū)別與總結(jié)

[摘要]上述的核心區(qū)別導(dǎo)致了一系列的細(xì)節(jié)上的區(qū)別。    首先,前面敘述的所有方法都隸屬于 Thread 類(lèi),但是這一對(duì)卻直接隸屬于 Object 類(lèi),也就是說(shuō),所有對(duì)象都擁有這一對(duì)方法。初看起來(lái)這十分不可思議,但是實(shí)際上卻是很自然的,因?yàn)檫@一對(duì)方法阻塞時(shí)要釋放占用的鎖,而鎖是任何對(duì)象都具有的,調(diào)用任意對(duì)...
上述的核心區(qū)別導(dǎo)致了一系列的細(xì)節(jié)上的區(qū)別。

   首先,前面敘述的所有方法都隸屬于 Thread 類(lèi),但是這一對(duì)卻直接隸屬于 Object 類(lèi),也就是說(shuō),所有對(duì)象都擁有這一對(duì)方法。初看起來(lái)這十分不可思議,但是實(shí)際上卻是很自然的,因?yàn)檫@一對(duì)方法阻塞時(shí)要釋放占用的鎖,而鎖是任何對(duì)象都具有的,調(diào)用任意對(duì)象的 wait() 方法導(dǎo)致線程阻塞,并且該對(duì)象上的鎖被釋放。而調(diào)用 任意對(duì)象的notify()方法則導(dǎo)致因調(diào)用該對(duì)象的 wait() 方法而阻塞的線程中隨機(jī)選擇的一個(gè)解除阻塞(但要等到獲得鎖后才真正可執(zhí)行)。

   其次,前面敘述的所有方法都可在任何位置調(diào)用,但是這一對(duì)方法卻必須在 synchronized 方法或塊中調(diào)用,理由也很簡(jiǎn)單,只有在synchronized 方法或塊中當(dāng)前線程才占有鎖,才有鎖可以釋放。同樣的道理,調(diào)用這一對(duì)方法的對(duì)象上的鎖必須為當(dāng)前線程所擁有,這樣才有鎖可以釋放。因此,這一對(duì)方法調(diào)用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的上鎖對(duì)象就是調(diào)用這一對(duì)方法的對(duì)象。若不滿足這一條件,則程序雖然仍能編譯,但在運(yùn)行時(shí)會(huì)出現(xiàn)IllegalMonitorStateException 異常。

   wait() 和 notify() 方法的上述特性決定了它們經(jīng)常和synchronized 方法或塊一起使用,將它們和操作系統(tǒng)的進(jìn)程間通信機(jī)制作一個(gè)比較就會(huì)發(fā)現(xiàn)它們的相似性:synchronized方法或塊提供了類(lèi)似于操作系統(tǒng)原語(yǔ)的功能,它們的執(zhí)行不會(huì)受到多線程機(jī)制的干擾,而這一對(duì)方法則相當(dāng)于 block 和wakeup 原語(yǔ)(這一對(duì)方法均聲明為 synchronized)。它們的結(jié)合使得我們可以實(shí)現(xiàn)操作系統(tǒng)上一系列精妙的進(jìn)程間通信的算法(如信號(hào)量算法),并用于解決各種復(fù)雜的線程間通信問(wèn)題。

   關(guān)于 wait() 和 notify() 方法最后再說(shuō)明兩點(diǎn):

   第一:調(diào)用 notify() 方法導(dǎo)致解除阻塞的線程是從因調(diào)用該對(duì)象的 wait() 方法而阻塞的線程中隨機(jī)選取的,我們無(wú)法預(yù)料哪一個(gè)線程將會(huì)被選擇,所以編程時(shí)要特別小心,避免因這種不確定性而產(chǎn)生問(wèn)題。

   第二:除了 notify(),還有一個(gè)方法 notifyAll() 也可起到類(lèi)似作用,唯一的區(qū)別在于,調(diào)用 notifyAll() 方法將把因調(diào)用該對(duì)象的 wait() 方法而阻塞的所有線程一次性全部解除阻塞。當(dāng)然,只有獲得鎖的那一個(gè)線程才能進(jìn)入可執(zhí)行狀態(tài)。

   談到阻塞,就不能不談一談死鎖,略一分析就能發(fā)現(xiàn),suspend() 方法和不指定超時(shí)期限的 wait() 方法的調(diào)用都可能產(chǎn)生死鎖。遺憾的是,Java 并不在語(yǔ)言級(jí)別上支持死鎖的避免,我們?cè)诰幊讨斜仨毿⌒牡乇苊馑梨i。

   以上我們對(duì) Java 中實(shí)現(xiàn)線程阻塞的各種方法作了一番分析,我們重點(diǎn)分析了 wait() 和 notify() 方法,因?yàn)樗鼈兊墓δ茏顝?qiáng)大,使用也最靈活,但是這也導(dǎo)致了它們的效率較低,較容易出錯(cuò)。實(shí)際使用中我們應(yīng)該靈活使用各種方法,以便更好地達(dá)到我們的目的。

   七:守護(hù)線程

   守護(hù)線程是一類(lèi)特殊的線程,它和普通線程的區(qū)別在于它并不是應(yīng)用程序的核心部分,當(dāng)一個(gè)應(yīng)用程序的所有非守護(hù)線程終止運(yùn)行時(shí),即使仍然有守護(hù)線程在運(yùn)行,應(yīng)用程序也將終止,反之,只要有一個(gè)非守護(hù)線程在運(yùn)行,應(yīng)用程序就不會(huì)終止。守護(hù)線程一般被用于在后臺(tái)為其它線程提供服務(wù)。

   可以通過(guò)調(diào)用方法 isDaemon() 來(lái)判斷一個(gè)線程是否是守護(hù)線程,也可以調(diào)用方法 setDaemon() 來(lái)將一個(gè)線程設(shè)為守護(hù)線程。

   八:線程組

   線程組是一個(gè) Java 特有的概念,在 Java 中,線程組是類(lèi)ThreadGroup 的對(duì)象,每個(gè)線程都隸屬于唯一一個(gè)線程組,這個(gè)線程組在線程創(chuàng)建時(shí)指定并在線程的整個(gè)生命期內(nèi)都不能更改。你可以通過(guò)調(diào)用包含 ThreadGroup 類(lèi)型參數(shù)的 Thread 類(lèi)構(gòu)造函數(shù)來(lái)指定線程屬的線程組,若沒(méi)有指定,則線程缺省地隸屬于名為 system 的系統(tǒng)線程組。

   在 Java 中,除了預(yù)建的系統(tǒng)線程組外,所有線程組都必須顯式創(chuàng)建。在 Java 中,除系統(tǒng)線程組外的每個(gè)線程組又隸屬于另一個(gè)線程組,你可以在創(chuàng)建線程組時(shí)指定其所隸屬的線程組,若沒(méi)有指定,則缺省地隸屬于系統(tǒng)線程組。這樣,所有線程組組成了一棵以系統(tǒng)線程組為根的樹(shù)。

   Java 允許我們對(duì)一個(gè)線程組中的所有線程同時(shí)進(jìn)行操作,比如我們可以通過(guò)調(diào)用線程組的相應(yīng)方法來(lái)設(shè)置其中所有線程的優(yōu)先級(jí),也可以啟動(dòng)或阻塞其中的所有線程。

   Java 的線程組機(jī)制的另一個(gè)重要作用是線程安全。線程組機(jī)制允許我們通過(guò)分組來(lái)區(qū)分有不同安全特性的線程,對(duì)不同組的線程進(jìn)行不同的處理,還可以通過(guò)線程組的分層結(jié)構(gòu)來(lái)支持不對(duì)等安全措施的采用。Java 的 ThreadGroup 類(lèi)提供了大量的方法來(lái)方便我們對(duì)線程組樹(shù)中的每一個(gè)線程組以及線程組中的每一個(gè)線程進(jìn)行操作。

   九:總結(jié)
   在本文中,我們講述了 Java 多線程編程的方方面面,包括創(chuàng)建線程,以及對(duì)多個(gè)線程進(jìn)行調(diào)度、管理。我們深刻認(rèn)識(shí)到了多線程編程的復(fù)雜性,以及線程切換開(kāi)銷(xiāo)帶來(lái)的多線程程序的低效性,這也促使我們認(rèn)真地思考一個(gè)問(wèn)題:我們是否需要多線程?何時(shí)需要多線程?

   多線程的核心在于多個(gè)代碼塊并發(fā)執(zhí)行,本質(zhì)特點(diǎn)在于各代碼塊之間的代碼是亂序執(zhí)行的。我們的程序是否需要多線程,就是要看這是否也是它的內(nèi)在特點(diǎn)。

   假如我們的程序根本不要求多個(gè)代碼塊并發(fā)執(zhí)行,那自然不需要使用多線程;假如我們的程序雖然要求多個(gè)代碼塊并發(fā)執(zhí)行,但是卻不要求亂序,則我們完全可以用一個(gè)循環(huán)來(lái)簡(jiǎn)單高效地實(shí)現(xiàn),也不需要使用多線程;只有當(dāng)它完全符合多線程的特點(diǎn)時(shí),多線程機(jī)制對(duì)線程間通信和線程管理的強(qiáng)大支持才能有用武之地,這時(shí)使用多線程才是值得的。