版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、程序是很簡易的。然而,在編程人員面前,多線程呈現(xiàn)出了一組新的難題,如果沒有被恰當(dāng)?shù)慕鉀Q,將導(dǎo)致意外的行為以及細(xì)微的、難以發(fā)現(xiàn)的錯誤。 在本篇文章中,我們針對這些難題之一:如何中斷一個正在運(yùn)行的線程。 背景 中斷(Interrupt)一個線程意味著在該線程完成任務(wù)之前停止其正在進(jìn)行的一切,有效地中止其當(dāng)前的操作。線程是死亡、還是等待新的任務(wù)或是繼續(xù)運(yùn)行至下一步,就取決于這個程序。雖然初次看來它可能顯得簡單,但是,你必須進(jìn)行一些預(yù)警以實現(xiàn)期望的結(jié)果。你最好還是牢記以下的幾點告誡。 首先,忘掉Thread.stop方法。雖然它確實停止了一個正在運(yùn)行的線程,然而,這種方法是不安全也是不受提倡的,這意味
2、著,在未來的JAVA版本中,它將不復(fù)存在。 一些輕率的家伙可能被另一種方法Terrupt所迷惑。盡管,其名稱似乎在暗示著什么,然而,這種方法并不會中斷一個正在運(yùn)行的線程(待會將進(jìn)一步說明),正如Listing A中描述的那樣。它創(chuàng)建了一個線程,并且試圖使用Terrupt方法停止該線程。Thread.sleep()方法的調(diào)用,為線程的初始化和中止提供了充裕的時間。線程本身并不參與任何有用的操作。 class Example1 extends Thread boolean stop=false; public static void main( String a
3、rgs ) throws Exception Example1 thread = new Example1(); System.out.println( "Starting thread." ); thread.start(); Thread.sleep( 3000 ); System.out.println( "Interrupting thread." ); errupt(); Thread.sleep( 3000 ); System.out.println("Stopping application." );
4、 /System.exit(0); public void run() while(!stop) System.out.println( "Thread is running." ); long time = System.currentTimeMillis(); while(System.currentTimeMillis()-time < 1000) System.out.println("Thread exiting under request." ); 如果你運(yùn)行了Listing A中的代碼,你將在控制臺看到以下輸出:Starting th
5、read.Thread is running.Thread is running.Thread is running.Interrupting thread.Thread is running.Thread is running.Thread is running.Stopping application.Thread is running.Thread is running.Thread is running. 甚至,在Terrupt()被調(diào)用后,線程仍然繼續(xù)運(yùn)行。真正地中斷一個線程 中斷線程最好的,最受推薦的方式是,使用共享變量(shared variable)發(fā)出信號,
6、告訴線程必須停止正在運(yùn)行的任務(wù)。線程必須周期性的核查這一變量(尤其在冗余操作期間),然后有秩序地中止任務(wù)。Listing B描述了這一方式。Listing Bclass Example2 extends Thread volatile boolean stop = false; public static void main( String args ) throws Exception Example2 thread = new Example2(); System.out.println( "Starting thread." ); thread.start(); Th
7、read.sleep( 3000 ); System.out.println( "Asking thread to stop." ); thread.stop = true; Thread.sleep( 3000 ); System.out.println( "Stopping application." ); /System.exit( 0 ); public void run() while ( !stop ) System.out.println( "Thread is running." ); long time = Syst
8、em.currentTimeMillis(); while ( (System.currentTimeMillis()-time < 1000) && (!stop) ) System.out.println( "Thread exiting under request." ); 運(yùn)行Listing B中的代碼將產(chǎn)生如下輸出(注意線程是如何有秩序的退出的)Starting thread.Thread is running.Thread is running.Thread is running.Asking thread to stop.Thread e
9、xiting under request.Stopping application. 雖然該方法要求一些編碼,但并不難實現(xiàn)。同時,它給予線程機(jī)會進(jìn)行必要的清理工作,這在任何一個多線程應(yīng)用程序中都是絕對需要的。請確認(rèn)將共享變量定義成volatile 類型或?qū)λ囊磺性L問封入同步的塊/方法(synchronized blocks/methods)中。到目前為止一切順利!但是,當(dāng)線程等待某些事件發(fā)生而被阻塞,又會發(fā)生什么?當(dāng)然,如果線程被阻塞,它便不能核查共享變量,也就不能停止。這在許多情況下會發(fā)生,例如調(diào)用Object.wait()、ServerSocket.accept()和DatagramS
10、ocket.receive()時,這里僅舉出一些。他們都可能永久的阻塞線程。即使發(fā)生超時,在超時期滿之前持續(xù)等待也是不可行和不適當(dāng)?shù)?,所以,要使用某種機(jī)制使得線程更早地退出被阻塞的狀態(tài)。很不幸運(yùn),不存在這樣一種機(jī)制對所有的情況都適用,但是,根據(jù)情況不同卻可以使用特定的技術(shù)。在下面的環(huán)節(jié),我將解答一下最普遍的例子。使用Terrupt()中斷線程 正如Listing A中所描述的,Terrupt()方法不會中斷一個正在運(yùn)行的線程。這一方法實際上完成的是,在線程受到阻塞時拋出一個中斷信號,這樣線程就得以退出阻塞的狀態(tài)。更確切的說,如果線程被Object.wait,
11、 Thread.join和Thread.sleep三種方法之一阻塞,那么,它將接收到一個中斷異常(InterruptedException),從而提早地終結(jié)被阻塞狀態(tài)。 因此,如果線程被上述幾種方法阻塞,正確的停止線程方式是設(shè)置共享變量,并調(diào)用interrupt()(注意變量應(yīng)該先設(shè)置)。如果線程沒有被阻塞,這時調(diào)用interrupt()將不起作用;否則,線程就將得到異常(該線程必須事先預(yù)備好處理此狀況),接著逃離阻塞狀態(tài)。在任何一種情況中,最后線程都將檢查共享變量然后再停止。Listing C這個示例描述了該技術(shù)。Listing Cclass Example3 extends Thread
12、volatile boolean stop = false; public static void main( String args ) throws Exception Example3 thread = new Example3(); System.out.println( "Starting thread." ); thread.start(); Thread.sleep( 3000 ); System.out.println( "Asking thread to stop." ); thread.stop = true;/如果線程阻塞,將不會檢
13、查此變量 errupt(); Thread.sleep( 3000 ); System.out.println( "Stopping application." ); /System.exit( 0 ); public void run() while ( !stop ) System.out.println( "Thread running." ); try Thread.sleep( 1000 ); catch ( InterruptedException e ) System.out.println( "Thread
14、interrupted." ); System.out.println( "Thread exiting under request." ); 一旦Listing C中的Terrupt()被調(diào)用,線程便收到一個異常,于是逃離了阻塞狀態(tài)并確定應(yīng)該停止。運(yùn)行以上代碼將得到下面的輸出:Starting thread.Thread running.Thread running.Thread running.Asking thread to stop.Thread interrupted.Thread exiting under request.Stopp
15、ing application.中斷I/O操作 然而,如果線程在I/O操作進(jìn)行時被阻塞,又會如何?I/O操作可以阻塞線程一段相當(dāng)長的時間,特別是牽扯到網(wǎng)絡(luò)應(yīng)用時。例如,服務(wù)器可能需要等待一個請求(request),又或者,一個網(wǎng)絡(luò)應(yīng)用程序可能要等待遠(yuǎn)端主機(jī)的響應(yīng)。如果你正使用通道(channels)(這是在Java 1.4中引入的新的I/O API),那么被阻塞的線程將收到一個ClosedByInterruptException異常。如果情況是這樣,其代碼的邏輯和第三個例子中的是一樣的,只是異常不同而已。但是,你可能正使用Java1.0之前就存在的傳統(tǒng)的I/O,而且要求更多的工作。既然這樣,T
16、errupt()將不起作用,因為線程將不會退出被阻塞狀態(tài)。Listing D描述了這一行為。盡管interrupt()被調(diào)用,線程也不會退出被阻塞狀態(tài)Listing Dimport java.io.*;class Example4 extends Thread public static void main( String args ) throws Exception Example4 thread = new Example4(); System.out.println( "Starting thread." ); thread.start(); Th
17、read.sleep( 3000 ); System.out.println( "Interrupting thread." ); errupt(); Thread.sleep( 3000 ); System.out.println( "Stopping application." ); /System.exit( 0 ); public void run() ServerSocket socket; try socket = new ServerSocket(7856); catch ( IOException e ) System
18、.out.println( "Could not create the socket." ); return; while ( true ) System.out.println( "Waiting for connection." ); try Socket sock = socket.accept(); catch ( IOException e ) System.out.println( "accept() failed or interrupted." ); 很幸運(yùn),Java平臺為這種情形提供了一項解決方案,即調(diào)用阻塞該線程的
19、套接字的close()方法。在這種情形下,如果線程被I/O操作阻塞,該線程將接收到一個SocketException異常,這與使用interrupt()方法引起一個InterruptedException異常被拋出非常相似。唯一要說明的是,必須存在socket的引用(reference),只有這樣close()方法才能被調(diào)用。這意味著socket對象必須被共享。Listing E描述了這一情形。運(yùn)行邏輯和以前的示例是相同的。Listing Eimport .*;import java.io.*;class Example5 extends Thread volatile boolean sto
20、p = false; volatile ServerSocket socket; public static void main( String args ) throws Exception Example5 thread = new Example5(); System.out.println( "Starting thread." ); thread.start(); Thread.sleep( 3000 ); System.out.println( "Asking thread to stop." ); thread.stop = true; thread.socket.close(); Thread.sleep( 3000 ); System.out.println( "Stopping application." ); /System.e
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 強(qiáng)化酒店安全管理
- 蘇州工會課程設(shè)計
- 2024年設(shè)備監(jiān)理師考試題庫含答案(滿分必刷)
- 餐飲食品銷售顧問
- 鞋類設(shè)計師工作經(jīng)驗分享
- 秘書工作中的法律知識計劃
- 教育用品采購心得
- 化工行業(yè)安全管理經(jīng)驗分享
- 廣州市工商行政管理局網(wǎng)站政務(wù)服務(wù)操作指南
- 餐飲行業(yè)個人發(fā)展計劃
- 術(shù)中獲得性壓力性損傷預(yù)防
- 新課標(biāo)人教版五年級數(shù)學(xué)上冊總復(fù)習(xí)(全冊)
- 電氣接線工藝培訓(xùn)
- 土木工程管理與工程造價的有效控制探析獲獎科研報告
- 基層版創(chuàng)傷中心建設(shè)指南(試行)
- 全過程造價咨詢服務(wù)實施方案
- 插圖幻燈片制作PPT3D小人圖標(biāo)幻燈素材(精)
- 室內(nèi)設(shè)計裝飾材料案例分析課件
- 四年級上冊道德與法治第10課《我們所了解的環(huán)境污染》教學(xué)反思(部編人教版)
- GB/T 8491-2009高硅耐蝕鑄鐵件
- GB/T 15970.7-2000金屬和合金的腐蝕應(yīng)力腐蝕試驗第7部分:慢應(yīng)變速率試驗
評論
0/150
提交評論