Java多線程編程總結(jié)-9_第1頁
Java多線程編程總結(jié)-9_第2頁
Java多線程編程總結(jié)-9_第3頁
Java多線程編程總結(jié)-9_第4頁
Java多線程編程總結(jié)-9_第5頁
已閱讀5頁,還剩2頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Java多線程編程總結(jié)下面是Java線程系列博文的一個編目:

Java線程:概念與原理Java線程:創(chuàng)建與啟動Java線程:線程棧模型與線程的變量Java線程:線程狀態(tài)的轉(zhuǎn)換Java線程:線程的同步與鎖Java線程:線程的交互Java線程:線程的調(diào)度-休眠Java線程:線程的調(diào)度-優(yōu)先級Java線程:線程的調(diào)度-讓步Java線程:線程的調(diào)度-合并Java線程:線程的調(diào)度-守護線程Java線程:線程的同步-同步方法Java線程:線程的同步-同步塊Java線程:并發(fā)協(xié)作-生產(chǎn)者消費者模型Java線程:并發(fā)協(xié)作-死鎖Java線程:volatile關(guān)鍵字Java線程:新特征-線程池Java線程:新特征-有返回值的線程Java線程:新特征-鎖(上)Java線程:新特征-鎖(下)Java線程:新特征-信號量Java線程:新特征-阻塞隊列Java線程:新特征-阻塞棧Java線程:新特征-條件變量Java線程:新特征-原子量Java線程:新特征-障礙器Java線程:大總結(jié)下面的內(nèi)容是很早之前寫的,內(nèi)容不夠充實,而且是基于Java1.4的內(nèi)容,Java5之后,線程并發(fā)部分擴展了相當多的內(nèi)容,因此建議大家看上面的系列文章的內(nèi)容,與時俱進,跟上Java發(fā)展的步伐。

一、認識多任務、多進程、單線程、多線程要認識多線程就要從操作系統(tǒng)的原理說起。以前古老的DOS操作系統(tǒng)(V6.22)是單任務的,還沒有線程的概念,系統(tǒng)在每次只能做一件事情。比如你在copy東西的時候不能rename文件名。為了提高系統(tǒng)的利用效率,采用批處理來批量執(zhí)行任務?,F(xiàn)在的操作系統(tǒng)都是多任務操作系統(tǒng),每個運行的任務就是操作系統(tǒng)所做的一件事情,比如你在聽歌的同時還在用MSN和好友聊天。聽歌和聊天就是兩個任務,這個兩個任務是“同時”進行的。一個任務一般對應一個進程,也可能包含好幾個進程。比如運行的MSN就對應一個MSN的進程,如果你用的是windows系統(tǒng),你就可以在任務管理器中看到操作系統(tǒng)正在運行的進程信息。一般來說,當運行一個應用程序的時候,就啟動了一個進程,當然有些會啟動多個進程。啟動進程的時候,操作系統(tǒng)會為進程分配資源,其中最主要的資源是內(nèi)存空間,因為程序是在內(nèi)存中運行的。在進程中,有些程序流程塊是可以亂序執(zhí)行的,并且這個代碼塊可以同時被多次執(zhí)行。實際上,這樣的代碼塊就是線程體。線程是進程中亂序執(zhí)行的代碼流程。當多個線程同時運行的時候,這樣的執(zhí)行模式成為并發(fā)執(zhí)行。多線程的目的是為了最大限度的利用CPU資源。Java編寫程序都運行在在Java虛擬機(JVM)中,在JVM的內(nèi)部,程序的多任務是通過線程來實現(xiàn)的。每用java命令啟動一個java應用程序,就會啟動一個JVM進程。在同一個JVM進程中,有且只有一個進程,就是它自己。在這個JVM環(huán)境中,所有程序代碼的運行都是以線程來運行。一般常見的Java應用程序都是單線程的。比如,用java命令運行一個最簡單的HelloWorld的Java應用程序時,就啟動了一個JVM進程,JVM找到程序程序的入口點main(),然后運行main()方法,這樣就產(chǎn)生了一個線程,這個線程稱之為主線程。當main方法結(jié)束后,主線程運行完成。JVM進程也隨即退出。對于一個進程中的多個線程來說,多個線程共享進程的內(nèi)存塊,當有新的線程產(chǎn)生的時候,操作系統(tǒng)不分配新的內(nèi)存,而是讓新線程共享原有的進程塊的內(nèi)存。因此,線程間的通信很容易,速度也很快。不同的進程因為處于不同的內(nèi)存塊,因此進程之間的通信相對困難。實際上,操作的系統(tǒng)的多進程實現(xiàn)了多任務并發(fā)執(zhí)行,程序的多線程實現(xiàn)了進程的并發(fā)執(zhí)行。多任務、多進程、多線程的前提都是要求操作系統(tǒng)提供多任務、多進程、多線程的支持。

在Java程序中,JVM負責線程的調(diào)度。線程調(diào)度是值按照特定的機制為多個線程分配CPU的使用權(quán)。調(diào)度的模式有兩種:分時調(diào)度和搶占式調(diào)度。分時調(diào)度是所有線程輪流獲得CPU使用權(quán),并平均分配每個線程占用CPU的時間;搶占式調(diào)度是根據(jù)線程的優(yōu)先級別來獲取CPU的使用權(quán)。JVM的線程調(diào)度模式采用了搶占式模式。所謂的“并發(fā)執(zhí)行”、“同時”其實都不是真正意義上的“同時”。眾所周知,CPU都有個時鐘頻率,表示每秒中能執(zhí)行cpu指令的次數(shù)。在每個時鐘周期內(nèi),CPU實際上只能去執(zhí)行一條(也有可能多條)指令。操作系統(tǒng)將進程線程進行管理,輪流(沒有固定的順序)分配每個進程很短的一段是時間(不一定是均分),然后在每個線程內(nèi)部,程序代碼自己處理該進程內(nèi)部線程的時間分配,多個線程之間相互的切換去執(zhí)行,這個切換時間也是非常短的。因此多任務、多進程、多線程都是操作系統(tǒng)給人的一種宏觀感受,從微觀角度看,程序的運行是異步執(zhí)行的。

用一句話做總結(jié):雖然操作系統(tǒng)是多線程的,但CPU每一時刻只能做一件事,和人的大腦是一樣的,呵呵。

二、Java與多線程Java語言的多線程需要操作系統(tǒng)的支持。

Java虛擬機允許應用程序并發(fā)地運行多個執(zhí)行線程。Java語言提供了多線程編程的擴展點,并給出了功能強大的線程控制API。

在Java中,多線程的實現(xiàn)有兩種方式:擴展java.lang.Thread類實現(xiàn)java.lang.Runnable接口每個線程都有一個優(yōu)先級,高優(yōu)先級線程的執(zhí)行優(yōu)先于低優(yōu)先級線程。每個線程都可以或不可以標記為一個守護程序。當某個線程中運行的代碼創(chuàng)建一個新Thread對象時,該新線程的初始優(yōu)先級被設(shè)定為創(chuàng)建線程的優(yōu)先級,并且當且僅當創(chuàng)建線程是守護線程時,新線程才是守護程序。當Java虛擬機啟動時,通常都會有單個非守護線程(它通常會調(diào)用某個指定類的main方法)。Java虛擬機會繼續(xù)執(zhí)行線程,直到下列任一情況出現(xiàn)時為止:調(diào)用了Runtime類的exit方法,并且安全管理器允許退出操作發(fā)生。非守護線程的所有線程都已停止運行,無論是通過從對run方法的調(diào)用中返回,還是通過拋出一個傳播到run方法之外的異常。三、擴展java.lang.Thread類

/**

*FileName:

TestMitiThread.java

*Createdby:

IntelliJIDEA.

*Copyright:

Copyright(c)2003-2006

*Company:

Lavasoft([url]/[/url])

*Author:

leizhimin

*Modifier:

leizhimin

*DateTime:

2007-5-1710:03:12

*Readme:

通過擴展Thread類實現(xiàn)多線程

*/publicclassTestMitiThread{

publicstaticvoidmain(String[]rags){

System.out.println(Thread.currentThread().getName()+"線程運行開始!");

newMitiSay("A").start();

newMitiSay("B").start();

System.out.println(Thread.currentThread().getName()+"線程運行結(jié)束!");

}}

classMitiSayextendsThread{

publicMitiSay(StringthreadName){

super(threadName);}

publicvoidrun(){

System.out.println(getName()+"線程運行開始!");

for(inti=0;i<10;i++){

System.out.println(i+""+getName());

try{

sleep((int)Math.random()*10);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

System.out.println(getName()+"線程運行結(jié)束!");

}}

運行結(jié)果:main線程運行開始!main線程運行結(jié)束!A線程運行開始!0A1AB線程運行開始!2A0B3A4A1B5A6A7A8A9AA線程運行結(jié)束!2B3B4B5B6B7B8B9BB線程運行結(jié)束!

說明:程序啟動運行main時候,java虛擬機啟動一個進程,主線程main在main()調(diào)用時候被創(chuàng)建。隨著調(diào)用MitiSay的兩個對象的start方法,另外兩個線程也啟動了,這樣,整個應用就在多線程下運行。在一個方法中調(diào)用Thread.currentThread().getName()方法,可以獲取當前線程的名字。在mian方法中調(diào)用該方法,獲取的是主線程的名字。注意:start()方法的調(diào)用后并不是立即執(zhí)行多線程代碼,而是使得該線程變?yōu)榭蛇\行態(tài)(Runnable),什么時候運行是由操作系統(tǒng)決定的。從程序運行的結(jié)果可以發(fā)現(xiàn),多線程程序是亂序執(zhí)行。因此,只有亂序執(zhí)行的代碼才有必要設(shè)計為多線程。Thread.sleep()方法調(diào)用目的是不讓當前線程獨自霸占該進程所獲取的CPU資源,以留出一定時間給其他線程執(zhí)行的機會。實際上所有的多線程代碼執(zhí)行順序都是不確定的,每次執(zhí)行的結(jié)果都是隨機的。四、實現(xiàn)java.lang.Runnable接口/**

*通過實現(xiàn)Runnable接口實現(xiàn)多線程

*/pubuicclassTestMitiThread1implementsRunnable{

publicstaticvoidmain(String[]args){

System.out.println(Thread.currentThread().getName()+"線程運行開始!");

TestMitiThread1test=newTestMitiThread1();

Threadthread1=newThread(test);

Threadthread2=newThread(test);

thread1.start();

thread2.start();

System.out.println(Thread.currentThread().getName()+"線程運行結(jié)束!");

}

publicvoidrun(){

System.out.println(Thread.currentThread().getName()+"線程運行開始!");

for(inti=0;i<10;i++){

System.out.println(i+""+Thread.currentThread().getName());

try{

Thread.sleep((int)Math.random()*10);

}catch(InterruptedExceptione){

e.printStackTrace();

}

}

System.out.println(Thread.currentThread().getName()+"線程運行結(jié)束!");

}}

運行結(jié)果:

main線程運行開始!Thread-0線程運行開始!main線程運行結(jié)束!0Thread-0Thread-1線程運行開始!0Thread-11Thread-11Thread-02Thread-02Thread-13Thread-03Thread-14Thread-04Thread-15Thread-06Thread-05Thread-17Thread-08Thread-06Thread-19Thread-07Thread-1Thread-0線程運行結(jié)束!8Thread-19Thread-1Thread-1線程運行結(jié)束!

說明:TestMitiThread1類通過實現(xiàn)Runnable接口,使得該類有了多線程類的特征。run()方法是多線程程序的一個約定。所有的多線程代碼都在run方法里面。Thread類實際上也是實現(xiàn)了Runnable接口的類。在啟動的多線程的時候,需要先通過Thread類的構(gòu)造方法Thread(Runnabletarget)構(gòu)造出對象,然后調(diào)用Thread對象的start()方法來運行多線程代碼。實際上所有的多線程代碼都是通過運行Thread的start()方法來運行的。因此,不管是擴展Thread類還是實現(xiàn)Runnable接口來實現(xiàn)多線程,最終還是通過Thread的對象的API來控制線程的,熟悉Thread類的API是進行多線程編程的基礎(chǔ)。五、讀解Thread類APIstaticintMAX_PRIORITY線程可以具有的最高優(yōu)先級。staticintMIN_PRIORITY線程可以具有的最低優(yōu)先級。staticintNORM_PRIORITY分配給線程的默認優(yōu)先級。

構(gòu)造方法摘要Thread(Runnabletarget)分配新的Thread對象。Thread(Stringname)分配新的Thread對象。

方法摘要staticThreadcurrentThread()返回對當前正在執(zhí)行的線程對象的引用。

ClassLoadergetContextClassLoader()返回該線程的上下文ClassLoader。

longgetId()返回該線程的標識符。

StringgetName()返回該線程的名稱。

intgetPriority()返回線程的優(yōu)先級。

Thread.StategetState()返回該線程的狀態(tài)。

ThreadGroupgetThreadGroup()返回該線程所屬的線程組。staticbooleanholdsLock(Objectobj)當且僅當當前線程在指定的對象上保持監(jiān)視器鎖時,才返回true。

voidinterrupt()中斷線程。staticbooleaninterrupted()測試當前線程是否已經(jīng)中斷。

booleanisAlive()測試線程是否處于活動狀態(tài)。

booleanisDaemon()測試該線程是否為守護線程。

booleanisInterrupted()測試線程是否已經(jīng)中斷。

voidjoin()等待該線程終止。

voidjoin(longmillis)等待該線程終止的時間最長為millis毫秒。

voidjoin(longmillis,intnanos)等待該線程終止的時間最長為millis毫秒+nanos納秒。

voidresume()已過時。該方法只與suspend()一起使用,但suspend()已經(jīng)遭到反對,因為它具有死鎖傾向。有關(guān)更多信息,請參閱為何Thread.stop、Thread.suspend和Thread.resume遭到反對?。

voidrun()如果該線程是使用獨立的Runnable運行對象構(gòu)造的,則調(diào)用該Runnable對象的run方法;否則,該方法不執(zhí)行任何操作并返回。

voidsetContextClassLoader(ClassLoadercl)設(shè)置該線程的上下文ClassLoader。

voidsetDaemon(booleanon)將該線程標記為守護線程或用戶線程。staticvoidsetDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandlereh)設(shè)置當線程由于未捕獲到異常而突然終止,并且沒有為該線程定義其他處理程序時所調(diào)用的默認處理程序。

voidsetName(Stringname)改變線程名稱,使之與參數(shù)name相同。

voidsetPriority(intnewPriority)更改線程的優(yōu)先級。

voidsetUncaughtExceptionHandler(Thread.UncaughtExceptionHandlereh)設(shè)置該線程由于未捕獲到異常而突然終止時調(diào)用的處理程序。staticvoidsleep(longmillis)在指定的毫秒數(shù)內(nèi)讓當前正在執(zhí)行的線程休眠(暫停執(zhí)行)。staticvoidsleep(longmillis,intnanos)在指定的毫秒數(shù)加指定的納秒數(shù)內(nèi)讓當前正在執(zhí)行的線程休眠(暫停執(zhí)行)。

voidstart()使該線程開始執(zhí)行;Java虛擬機調(diào)用該線程的run方法。

voidstop()已過時。該方法具有固有的不安全性。用Thread.stop來終止線程將釋放它已經(jīng)鎖定的所有監(jiān)視器(作為沿堆棧向上傳播的未檢查ThreadDeath異常的一個自然后果)。如果以前受這些監(jiān)視器保護的任何對象都處于一種不一致的狀態(tài),則損壞的對象將對其他線程可見,這有可能導致任意的行為。stop的許多使用都應由只修改某些變量以指示目標線程應該停止運行的代碼來取代。目標線程應定期檢查該變量,并且如果該變量指示它要停止運行,則從其運行方法依次返回。如果目標線程等待很長時間(例如基于一個條件變量),則應使用interrupt方法來中斷該等待。有關(guān)更多信息,請參閱《為何不贊成使用Thread.stop、Thread.suspend和Thread.resume?》。

voidstop(Throwableobj)

已過時。該方法具有固有的不安全性。請參閱stop()以獲得詳細信息。該方法的附加危險是它可用于生成目標線程未準備處理的異常(包括若沒有該方法該線程不太可能拋出的已檢查的異常)。有關(guān)更多信息,請參閱為何Thread.stop、Thread.suspend和Thread.resume遭到反對?。

voidsuspend()已過時。該方法已經(jīng)遭到反對,因為它具有固有的死鎖傾向。如果目標線程掛起時在保護關(guān)鍵系統(tǒng)資源的監(jiān)視器上保持有鎖,則在目標線程重新開始以前任何線程都不能訪問該資源。如果重新開始目標線程的線程想在調(diào)用resume之前鎖定該監(jiān)視器,則會發(fā)生死鎖。這類死鎖通常會證明自己是“凍結(jié)”的進程。有關(guān)更多信息,請參閱為何Thread.stop、Thread.suspend和Thread.resume遭到反對?。

StringtoString()返回該線程的字符串表示形式,包括線程名稱、優(yōu)先級和線程組。staticvoidyield()暫停當前正在執(zhí)行的線程對象,并執(zhí)行其他線程。六、線程的狀態(tài)轉(zhuǎn)換圖線程在一定條件下,狀態(tài)會發(fā)生變化。線程變化的狀態(tài)轉(zhuǎn)換圖如下:

1、新建狀態(tài)(New):新創(chuàng)建了一個線程對象。2、就緒狀態(tài)(Runnable):線程對象創(chuàng)建后,其他線程調(diào)用了該對象的start()方法。該狀態(tài)的線程位于可運行線程池中,變得可運行,等待獲取CPU的使用權(quán)。3、運行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。4、阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因為某種原因放棄CPU使用權(quán),暫時停止運行。直到線程進入就緒狀態(tài),才有機會轉(zhuǎn)到運行狀態(tài)。阻塞的情況分三種:(一)、等待阻塞:運行的線程執(zhí)行wait()方法,JVM會把該線程放入等待池中。(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。(三)、其他阻塞:運行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請求時,JVM會把該線程置為阻塞狀態(tài)。當sleep()狀態(tài)超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉(zhuǎn)入就緒狀態(tài)。5、死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。七、線程的調(diào)度1、調(diào)整線程優(yōu)先級:Java線程有優(yōu)先級,優(yōu)先級高的線程會獲得較多的運行機會。Java線程的優(yōu)先級用整數(shù)表示,取值范圍是1~10,Thread類有以下三個靜態(tài)常量:staticintMAX_PRIORITY線程可以具有的最高優(yōu)先級,取值為10。staticintMIN_PRIORITY線程可以具有的最低優(yōu)先級,取值為1。staticintNORM_PRIORITY分配給線程的默認優(yōu)先級,取值為5。Thread類的setPriority()和getPriority()方法分別用來設(shè)置和獲取線程的優(yōu)先級。每個線程都有默認的優(yōu)先級。主線程的默認優(yōu)先級為Thread.NORM_PRIORITY。線程的優(yōu)先級有繼承關(guān)系,比如A線程中創(chuàng)建了B線程,那么B將和A具有相同的優(yōu)先級。JVM提供了10個線程優(yōu)先級,但與常見的操作系統(tǒng)都不能很好的映射。如果希望程序能

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論