日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

jar 退出run_Java终止线程的三种方式

發布時間:2023/12/10 java 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jar 退出run_Java终止线程的三种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

停止一個線程通常意味著在線程處理任務完成之前停掉正在做的操作,也就是放棄當前的操作。

在 Java 中有以下 3 種方法可以終止正在運行的線程:

使用退出標志,使線程正常退出,也就是當 run() 方法完成后線程中止。

使用 stop() 方法強行終止線程,但是不推薦使用這個方法,該方法已被棄用。

使用 interrupt 方法中斷線程。

1. 使用標志位終止線程

在 run() 方法執行完畢后,該線程就終止了。但是在某些特殊的情況下,run() 方法會被一直執行;比如在服務端程序中可能會使用 while(true) { ... } 這樣的循環結構來不斷的接收來自客戶端的請求。此時就可以用修改標志位的方式來結束 run() 方法。

public class ServerThread extends Thread {

//volatile修飾符用來保證其它線程讀取的總是該變量的最新的值

public volatile boolean exit = false;

@Override

public void run() {

ServerSocket serverSocket = new ServerSocket(8080);

while(!exit){

serverSocket.accept(); //阻塞等待客戶端消息

...

}

}

public static void main(String[] args) {

ServerThread t = new ServerThread();

t.start();

...

t.exit = true; //修改標志位,退出線程

}

}

2. 使用 stop() 終止線程

通過查看 JDK 的 API,我們會看到 java.lang.Thread 類型提供了一系列的方法如 start()、stop()、resume()、suspend()、destory()等方法來管理線程。但是除了 start() 之外,其它幾個方法都被聲名為已過時(deprecated)。

雖然 stop() 方法確實可以停止一個正在運行的線程,但是這個方法是不安全的,而且該方法已被棄用,最好不要使用它。

JDK 文檔中還引入用一篇文章來解釋了棄用這些方法的原因:《Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?》

為什么棄用stop:

調用 stop() 方法會立刻停止 run() 方法中剩余的全部工作,包括在 catch 或 finally 語句中的,并拋出ThreadDeath異常(通常情況下此異常不需要顯示的捕獲),因此可能會導致一些清理性的工作的得不到完成,如文件,數據庫等的關閉。

調用 stop() 方法會立即釋放該線程所持有的所有的鎖,導致數據得不到同步,出現數據不一致的問題。

例如,存在一個對象 u 持有 ID 和 NAME 兩個字段,假如寫入線程在寫對象的過程中,只完成了對 ID 的賦值,但沒來得及為 NAME 賦值,就被 stop() 導致鎖被釋放,那么當讀取線程得到鎖之后再去讀取對象 u 的 ID 和 Name 時,就會出現數據不一致的問題,如下圖:

3. 使用 interrupt() 中斷線程

現在我們知道了使用 stop() 方式停止線程是非常不安全的方式,那么我們應該使用什么方法來停止線程呢?答案就是使用 interrupt() 方法來中斷線程。

需要明確的一點的是:interrupt() 方法并不像在 for 循環語句中使用 break 語句那樣干脆,馬上就停止循環。調用 interrupt() 方法僅僅是在當前線程中打一個停止的標記,并不是真的停止線程。

也就是說,線程中斷并不會立即終止線程,而是通知目標線程,有人希望你終止。至于目標線程收到通知后會如何處理,則完全由目標線程自行決定。這一點很重要,如果中斷后,線程立即無條件退出,那么我們又會遇到 stop() 方法的老問題。

事實上,如果一個線程不能被 interrupt,那么 stop 方法也不會起作用。

我們來看一個使用 interrupt() 的例子:

public class InterruptThread1 extends Thread{

public static void main(String[] args) {

try {

InterruptThread1 t = new InterruptThread1();

t.start();

Thread.sleep(200);

t.interrupt();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

@Override

public void run() {

super.run();

for(int i = 0; i <= 200000; i++) {

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

}

}

}

輸出:

從輸出的結果我們會發現 interrupt 方法并沒有停止線程 t 中的處理邏輯,也就是說即使 t 線程被設置為了中斷狀態,但是這個中斷并不會起作用,那么該如何停止線程呢?

這就需要使用到另外兩個與線程中斷有關的方法了:

public boolean Thread.isInterrupted() //判斷是否被中斷

public static boolean Thread.interrupted() //判斷是否被中斷,并清除當前中斷狀態

這兩個方法使得當前線程能夠感知到是否被中斷了(通過檢查標志位)。

所以如果希望線程 t 在中斷后停止,就必須先判斷是否被中斷,并為它增加相應的中斷處理代碼:

@Override

public void run() {

super.run();

for(int i = 0; i <= 200000; i++) {

//判斷是否被中斷

if(Thread.currentThread().isInterrupted()){

//處理中斷邏輯

break;

}

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

}

}

輸出結果,for 循環在執行完成前就提前結束了:

在上面這段代碼中,我們增加了 Thread.isInterrupted() 來判斷當前線程是否被中斷了,如果是,則退出 for 循環,結束線程。

這種方式看起來與之前介紹的“使用標志位終止線程”非常類似,但是在遇到 sleep() 或者 wait() 這樣的操作,我們只能通過中斷來處理了。

public static native void sleep(long millis) throws InterruptedException

Thread.sleep() 方法會拋出一個 InterruptedException 異常,當線程被 sleep() 休眠時,如果被中斷,這會就拋出這個異常。

(注意:Thread.sleep() 方法由于中斷而拋出的異常,是會清除中斷標記的。)

總結

以上是生活随笔為你收集整理的jar 退出run_Java终止线程的三种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。