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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Java一个线程能否结束另一个永不停止的线程

發布時間:2023/11/27 生活经验 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java一个线程能否结束另一个永不停止的线程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在Java中停止一個線程有三種辦法?:

1.正常結束執行;

2.發生異常;

3.被其他線程stop(Java官方不建議)

參考:https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

為什么Thread.stop棄用?

因為它本質上是不安全的。停止線程會導致它解鎖已鎖定的所有監視器。(當ThreadDeath異常傳播到堆棧中時,監視器將被解鎖。)如果先前受這些監視器保護的任何對象處于不一致狀態,則其他線程現在可以以不一致的狀態查看這些對象。據說這些物體已被?損壞。當線程對受損對象進行操作時,可能會導致任意行為。這種行為可能很微妙并且難以檢測,或者可能是明顯的。與其他未經檢查的異常不同,它會?ThreadDeath默默地殺死線程;?因此,用戶沒有警告他的程序可能被破壞。

?

所以如果遇到一種特殊情況某一個線程A會一直執行下去停不下來,這種情況是存在的比如那種需要持續取樣的線程A,當然了在正常代碼里會有“停止”功能,外部線程B可以發送停止信號給A,A可以直接結束。

如果A線程沒有這種信號量那么B線程還可以主動停止他么?答案是不可以!

public class Test {public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();int a = 0;while (a < 100) {Thread.sleep(1000);a++;if (a == 3) {a = 100;thread1.interrupt();//thread1.stop();//throw new RuntimeException("主函數拋出異常");}}}public static void fun_a() {for (; ; ) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(">> " + DateUtil.getNowTimeString());}}
}

?可以看到interrupt并不能讓運行中的線程停止,這個是很容易被誤解的地方。這個方法的作用并不是中斷線程,而是設置一個標識,通知該線程可以被中斷了,到底是繼續執行,還是中斷返回,由線程本身自己決定。

當對一個線程調用了interrupt()之后,如果該線程處于被阻塞狀態(比如執行了wait、sleep或join等方法),那么會立即退出阻塞狀態,并拋出一個InterruptedException異常,在代碼中catch這個異常進行后續處理。如果線程一直處于運行狀態,那么只會把該線程的中斷標志設置為 true,僅此而已,所以interrupt()并不能真正的中斷線程,不過在rpc調用的場景中,請求線程一般都處于阻塞狀態,等待數據返回,這時interrupt()方法是可以派上用場的。

參考:Java中如何實現線程的超時中斷

?

修改子線程的代碼:

public static void fun_a() {for (; ; ) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException("子線程拋出異常");//e.printStackTrace();}System.out.println(">> " + DateUtil.getNowTimeString());}}

這次是可以結束子線程,前提是子線程自己有異常捕獲機制,可以接受其他線程發來的InterruptedException:

?

主線程每隔2秒對子線程進行一次Interrupted:

package com.t.www;public class Test {final static Object lock = new Object();volatile boolean stop = false;public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();System.out.println("> 1 主線程start " + DateUtil.getNowTimeString());int a = 0;while (a < 3) {Thread.sleep(2000);a++;System.out.println("> 2 主線程對子線程開始interrupt " + DateUtil.getNowTimeString());thread1.interrupt();System.out.println("> 3 主線程對子線程完成interrupt " + DateUtil.getNowTimeString());}}public static void fun_a() {for (; ; ) {try {System.out.println(">> 1 子線程wait " + DateUtil.getNowTimeString());synchronized (lock) {lock.wait();}Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子線程拋出異常");e.printStackTrace();}System.out.println(">> 2 子線程完成 " + DateUtil.getNowTimeString());}}
}

?

?修改子線程代碼:

try {System.out.println(">> 1 子線程wait " + DateUtil.getNowTimeString());synchronized (lock) {lock.wait();}Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子線程拋出異常");//e.printStackTrace();System.out.println(">> 2 子線程捕獲異常 " + DateUtil.getNowTimeString());}

從運行結果看和前面一致,只是沒有拋出異常。?

?

修改代碼子線程使用while(!Thread.currentThread().isInterrupted())判斷:

public class Test {public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();System.out.println("> 1 主線程start " + DateUtil.getNowTimeString());int a = 0;while (a < 3) {Thread.sleep(2000);a++;System.out.println("> 2 主線程對子線程開始interrupt " + DateUtil.getNowTimeString());thread1.interrupt();System.out.println("> 3 主線程對子線程完成interrupt " + DateUtil.getNowTimeString());}}public static void fun_a() {while(!Thread.currentThread().isInterrupted()){try {System.out.println(">> 1 子線程 " + DateUtil.getNowTimeString());Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子線程拋出異常");//e.printStackTrace();System.out.println(">> 2 子線程捕獲異常 " + DateUtil.getNowTimeString());}System.out.println(">> 3 子線程完成 " + DateUtil.getNowTimeString());}System.out.println(">> 4 子線程正常結束 " + DateUtil.getNowTimeString());}
}

可以看到這次因為子線程增加了狀態判斷所以可以正常結束:?

比較優雅的方式是使用一個變量在線程間通信,需要注意的是要保證可見性:

public class Test {private static volatile boolean finished = false;   // ① volatile條件變量public static void main(String args[]) throws InterruptedException {Thread thread1 = new Thread() {public void run() {fun_a();}};thread1.start();System.out.println("> 1 主線程start " + DateUtil.getNowTimeString());int a = 0;while (a < 3) {Thread.sleep(2000);a++;}System.out.println("> 1 主線程 a=" +a+" "+ DateUtil.getNowTimeString());finished=true;}public static void fun_a() {while(!finished){try {System.out.println(">> 1 子線程 " + DateUtil.getNowTimeString());Thread.sleep(1000);} catch (InterruptedException e) {//throw new RuntimeException("子線程拋出異常");//e.printStackTrace();System.out.println(">> 2 子線程捕獲異常 " + DateUtil.getNowTimeString());}System.out.println(">> 3 子線程完成 " + DateUtil.getNowTimeString());}System.out.println(">> 4 子線程正常結束 " + DateUtil.getNowTimeString());}
}

------------------

如何停止線程或任務

?

如何停止一個正在運行的java線程

了解Java中的線程中斷

如何在Java中正確停止Thread?

你如何殺死Java中的線程?

如何在運行時停止/終止長時間運行的Java線程?超時 - >取消 - >中斷狀態

Java - 從不同的類停止線程

https://javaconceptoftheday.com/how-to-stop-a-thread-in-java/

如何超時一個線程

?

參考《Effective Java 中文版 第3版

總結

以上是生活随笔為你收集整理的Java一个线程能否结束另一个永不停止的线程的全部內容,希望文章能夠幫你解決所遇到的問題。

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