如何中斷線程_第1頁
如何中斷線程_第2頁
如何中斷線程_第3頁
如何中斷線程_第4頁
如何中斷線程_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論