激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|

服務器之家 - 編程語言 - JAVA教程 - Java interrupt()方法使用注意_動力節點Java學院整理

Java interrupt()方法使用注意_動力節點Java學院整理

2020-10-26 16:25動力節點 JAVA教程

這篇文章主要介紹了Java interrupt()方法使用注意_動力節點Java學院整理,需要的朋友可以參考下

程序是很簡易的。然而,在編程人員面前,多線程呈現出了一組新的難題,如果沒有被恰當的解決,將導致意外的行為以及細微的、難以發現的錯誤。

  在本篇文章中,我們針對這些難題之一:如何中斷一個正在運行的線程。

背景

    中斷(Interrupt)一個線程意味著在該線程完成任務之前停止其正在進行的一切,有效地中止其當前的操作。線程是死亡、還是等待新的任務或是繼續運行至下一步,就取決于這個程序。雖然初次看來它可能顯得簡單,但是,你必須進行一些預警以實現期望的結果。你最好還是牢記以下的幾點告誡。

    首先,忘掉Thread.stop方法。雖然它確實停止了一個正在運行的線程,然而,這種方法是不安全也是不受提倡的,這意味著,在未來的Java版本中,它將不復存在。

    一些輕率的家伙可能被另一種方法Thread.interrupt所迷惑。盡管,其名稱似乎在暗示著什么,然而,這種方法并不會中斷一個正在運行的線程(待會將進一步說明),正如Listing A中描述的那樣。它創建了一個線程,并且試圖使用Thread.interrupt方法停止該線程。Thread.sleep()方法的調用,為線程的初始化和中止提供了充裕的時間。線程本身并不參與任何有用的操作。

Listing A 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Example1 extends Thread {
    boolean stop=false;
    public static void main( String args[] ) throws Exception {
    Example1 thread = new Example1();
    System.out.println( "Starting thread..." );
    thread.start();
    Thread.sleep( 3000 );
    System.out.println( "Interrupting thread..." );
    thread.interrupt();
    Thread.sleep( 3000 );
    System.out.println("Stopping application..." );
    //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..." );
    }
    }

如果你運行了Listing A中的代碼,你將在控制臺看到以下輸出:

Starting thread...
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...
...............................

甚至,在Thread.interrupt()被調用后,線程仍然繼續運行。

真正地中斷一個線程

    中斷線程最好的,最受推薦的方式是,使用共享變量(shared variable)發出信號,告訴線程必須停止正在運行的任務。線程必須周期性的核查這一變量(尤其在冗余操作期間),然后有秩序地中止任務。Listing B描述了這一方式。

Listing B 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class 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();
 Thread.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 = System.currentTimeMillis();
  while ( (System.currentTimeMillis()-time < 1000) && (!stop) ) {
  }
  }
 System.out.println( "Thread exiting under request..." );
 }
 }

運行Listing B中的代碼將產生如下輸出(注意線程是如何有秩序的退出的)

Starting thread...
Thread is running...
Thread is running...
Thread is running...
Asking thread to stop...
Thread exiting under request...
Stopping application...

   雖然該方法要求一些編碼,但并不難實現。同時,它給予線程機會進行必要的清理工作,這在任何一個多線程應用程序中都是絕對需要的。請確認將共享變量定義成volatile 類型或將對它的一切訪問封入同步的塊/方法(synchronized blocks/methods)中。

到目前為止一切順利!但是,當線程等待某些事件發生而被阻塞,又會發生什么?當然,如果線程被阻塞,它便不能核查共享變量,也就不能停止。這在許多情況下會發生,例如調用Object.wait()、ServerSocket.accept()和DatagramSocket.receive()時,這里僅舉出一些。

他們都可能永久的阻塞線程。即使發生超時,在超時期滿之前持續等待也是不可行和不適當的,所以,要使用某種機制使得線程更早地退出被阻塞的狀態。

很不幸運,不存在這樣一種機制對所有的情況都適用,但是,根據情況不同卻可以使用特定的技術。在下面的環節,我將解答一下最普遍的例子。

使用Thread.interrupt()中斷線程

  正如Listing A中所描述的,Thread.interrupt()方法不會中斷一個正在運行的線程。這一方法實際上完成的是,在線程受到阻塞時拋出一個中斷信號,這樣線程就得以退出阻塞的狀態。更確切的說,如果線程被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,那么,它將接收到一個中斷異常(InterruptedException),從而提早地終結被阻塞狀態。

    因此,如果線程被上述幾種方法阻塞,正確的停止線程方式是設置共享變量,并調用interrupt()(注意變量應該先設置)。如果線程沒有被阻塞,這時調用interrupt()將不起作用;否則,線程就將得到異常(該線程必須事先預備好處理此狀況),接著逃離阻塞狀態。在任何一種情況中,最后線程都將檢查共享變量然后再停止。Listing C這個示例描述了該技術。

Listing C

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Example3 extends Thread {
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;//如果線程阻塞,將不會檢查此變量
thread.interrupt();
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 interrupted..." );
 }
 }
System.out.println( "Thread exiting under request..." );
}
}

一旦Listing C中的Thread.interrupt()被調用,線程便收到一個異常,于是逃離了阻塞狀態并確定應該停止。運行以上代碼將得到下面的輸出:

Starting thread...
Thread running...
Thread running...
Thread running...
Asking thread to stop...
Thread interrupted...
Thread exiting under request...
Stopping application...

中斷I/O操作

    然而,如果線程在I/O操作進行時被阻塞,又會如何?I/O操作可以阻塞線程一段相當長的時間,特別是牽扯到網絡應用時。例如,服務器可能需要等待一個請求(request),又或者,一個網絡應用程序可能要等待遠端主機的響應。

如果你正使用通道(channels)(這是在Java 1.4中引入的新的I/O API),那么被阻塞的線程將收到一個ClosedByInterruptException異常。如果情況是這樣,其代碼的邏輯和第三個例子中的是一樣的,只是異常不同而已。

但是,你可能正使用Java1.0之前就存在的傳統的I/O,而且要求更多的工作。既然這樣,Thread.interrupt()將不起作用,因為線程將不會退出被阻塞狀態。Listing D描述了這一行為。盡管interrupt()被調用,線程也不會退出被阻塞狀態

Listing D

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import 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();
Thread.sleep( 3000 );
System.out.println( "Interrupting thread..." );
thread.interrupt();
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.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..." );
 }
 }
}
}

 很幸運,Java平臺為這種情形提供了一項解決方案,即調用阻塞該線程的套接字的close()方法。在這種情形下,如果線程被I/O操作阻塞,該線程將接收到一個SocketException異常,這與使用interrupt()方法引起一個InterruptedException異常被拋出非常相似。

唯一要說明的是,必須存在socket的引用(reference),只有這樣close()方法才能被調用。這意味著socket對象必須被共享。Listing E描述了這一情形。運行邏輯和以前的示例是相同的。

Listing E

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.net.*;
import java.io.*;
class Example5 extends Thread {
volatile boolean stop = 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.exit( 0 );
}
public void run() {
 try {
 socket = new ServerSocket(7856);
 } catch ( IOException e ) {
 System.out.println( "Could not create the socket..." );
 return;
 }
 while ( !stop ) {
 System.out.println( "Waiting for connection..." );
 try {
 Socket sock = socket.accept();
 } catch ( IOException e ) {
 System.out.println( "accept() failed or interrupted..." );
 }
 }
System.out.println( "Thread exiting under request..." );
}
}

以下是運行Listing E中代碼后的輸出:

?
1
2
3
4
5
6
Starting thread...
Waiting for connection...
Asking thread to stop...
accept() failed or interrupted...
Thread exiting under request...
Stopping application...

多線程是一個強大的工具,然而它正呈現出一系列難題。其中之一是如何中斷一個正在運行的線程。如果恰當地實現,使用上述技術中斷線程將比使用Java平臺上已經提供的內嵌操作更為簡單。

以上所述是小編給大家介紹的Java interrupt()方法使用注意,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!

延伸 · 閱讀

精彩推薦
  • JAVA教程Spring Boot Mysql 數據庫操作示例

    Spring Boot Mysql 數據庫操作示例

    本篇文章主要介紹了Spring Boot Mysql 數據庫操作示例,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    空心菜的愛3642020-08-19
  • JAVA教程詳解SpringMVC重定向傳參數的實現

    詳解SpringMVC重定向傳參數的實現

    本篇文章主要介紹了詳解SpringMVC重定向傳參數的實現,我們可以使用重定向的方式,改變瀏覽器的地址欄,防止表單因為刷新重復提交。有興趣的可以了解...

    Joepis3242020-07-30
  • JAVA教程java解析xml之dom4j解析xml示例分享

    java解析xml之dom4j解析xml示例分享

    DOM4J具有性能優異、功能強大和極端易用使用的特點,只要懂得DOM基本概念,就可以通過dom4j的api文檔來解析xml,dom4j是一套開源的api。實際項目中,往往選擇...

    java教程網2532019-10-29
  • JAVA教程Java如何在List或Map遍歷過程中刪除元素

    Java如何在List或Map遍歷過程中刪除元素

    相信大家在日常的開發過程中,經常需要對List或Map里面的符合某種業務的數據進行刪除,但是如果不了解里面的機制就容易掉入“陷阱”導致遺漏或者程序...

    daisy3352020-07-09
  • JAVA教程java實現文本文件刪除空行的示例分享

    java實現文本文件刪除空行的示例分享

    這篇文章主要介紹了java實現文本文件刪除空行的示例,需要的朋友可以參考下 ...

    java教程網3072019-11-17
  • JAVA教程Java遍歷集合的三種方式

    Java遍歷集合的三種方式

    本文主要對于遍歷集合獲取其對象,總結的三種簡單的方式進行介紹,文章中舉了兩個案例進行對比,具有很好的參考價值,下面就跟小編一起來看下吧...

    Bigerf4872020-07-14
  • JAVA教程如何設計一個秒殺系統

    如何設計一個秒殺系統

    本文主要介紹了如何設計一個秒殺系統的相關知識。具有很好的參考價值。下面跟著小編一起來看下吧...

    Heaven-Wang1882020-08-29
  • JAVA教程Java Integer及int裝箱拆箱對比

    Java Integer及int裝箱拆箱對比

    這篇文章主要介紹了Java Integer及int裝箱拆箱對比,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考...

    bf3782762020-09-15
主站蜘蛛池模板: 一区二区久久精品66国产精品 | 日本精品二区 | 56av国产精品久久久久久久 | 免费一级欧美在线观看视频 | 国产精品国产成人国产三级 | 免费黄色短视频网站 | 亚洲国产馆 | 欧美成人一级片 | 成年人免费视频播放 | 999久久久国产999久久久 | xxxx18韩国护士hd老师 | 草操视频 | 成人免费观看av | 精品成人在线观看 | 成人在线免费视频播放 | 九色中文字幕 | 久久久成人999亚洲区美女 | 妇子乱av一区二区三区 | 午夜精品福利影院 | 欧美成人午夜精品久久久 | 成人福利在线观看 | 黄色网战入口 | 国产 日韩 亚洲 欧美 | 日韩深夜视频 | 亚a在线| 日韩视频一区二区三区在线观看 | 欧美成人午夜一区二区三区 | 中国av免费在线观看 | 在线a毛片免费视频观看 | 免费黄色一级片 | 国产一区二区欧美 | 最新av在线播放 | 秋霞影院一二三区 | 福利在线免费视频 | 免费一级毛片在线播放视频 | 久久久亚洲欧美综合 | 欧美有码在线观看 | 亚洲小视频在线 | 二区成人 | 97超碰资源站 | 久久综合婷婷 |