欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)優(yōu)雅停止線程的有效方法詳解

 更新時間:2023年12月06日 16:54:02   作者:代碼小人物  
這篇文章主要為大家詳細(xì)如何安全有效停止 Java 線程的,確保多線程應(yīng)用程序平穩(wěn)運行并實現(xiàn)最佳資源管理,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

在Java中停止線程意味著在完成其任務(wù)之前停止正在進(jìn)行的操作,本質(zhì)上是放棄當(dāng)前操作。

雖然可以使用 Thread.stop() 方法停止線程,但強(qiáng)烈建議不要這樣做。雖然它確實終止了正在運行的線程,但此方法被認(rèn)為是不安全的并且已被棄用。

java中終止線程

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

  • 使用標(biāo)志:您可以創(chuàng)建一個boolean類型的標(biāo)志,線程定期檢查該標(biāo)志。當(dāng)該標(biāo)志設(shè)置為某個值時,線程可以優(yōu)雅地退出其執(zhí)行。
  • 使用interrupt()方法:可以使用interrupt()方法向線程發(fā)送中斷信號。
  • 使用Thread.stop()方法(不推薦):可以使用Thread.stop()方法強(qiáng)行停止正在運行的線程。然而,這種方法不被鼓勵并且被認(rèn)為是不安全的,因為它可能導(dǎo)致應(yīng)用程序中出現(xiàn)不可預(yù)測為。它已被棄用,應(yīng)該避免。

interrupt方法

使用interrupt()方法不會像帶有break語句的for循環(huán)一樣立即停止循環(huán)。它會在當(dāng)前線程內(nèi)設(shè)置一個停止標(biāo)志,但它不會立即停止線程。

public class MyThread extends Thread {
    public void run(){
        super.run();
        for(int i=0; i<500000; i++){
            System.out.println("i="+(i+1));
        }
    }
}

public class Run {
    public static void main(String args[]){
        Thread thread = new MyThread();
        thread.start();
        try {
            Thread.sleep(2000);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/*
結(jié)果:
...
i=499994
i=499995
i=499996
i=499997
i=499998
i=499999
i=500000
*/

如何檢查線程是否處于停止?fàn)顟B(tài)

Java中的提供了兩種方法:

  • this.interrupted():該方法檢測當(dāng)前線程(調(diào)用該方法的線程)是否已被中斷。它還具有清除當(dāng)前線程的中斷狀態(tài)的作用。
  • this.isInterrupted():此方法測試調(diào)用它的線程(不一定是當(dāng)前線程)是否已被中斷。它不會清除線程的中斷狀態(tài)。

這兩種方法有什么區(qū)別?

我們先看一下this.interrupted()方法:

public class MyThread extends Thread {
    public void run(){
        super.run();
        for(int i=0; i<500000; i++){
            i++;
            // System.out.println("i="+(i+1));
        }
    }
}

public class Run {
    public static void main(String args[]){
        Thread thread = new MyThread();
        thread.start();
        try {
            Thread.sleep(2000);
            thread.interrupt();

            System.out.println("stop 1??" + thread.interrupted());
            System.out.println("stop 2??" + thread.interrupted());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/*
---------------------------
結(jié)果:
stop 1??false
stop 2??false
*/

可以看到 Run 類中調(diào)用Thread對象的 Interrupt() 方法來檢查線程對象的線程是否已停止,控制臺輸出的內(nèi)容表明線程尚未停止。

這也證實了interrupted()方法,它用于檢測當(dāng)前線程(在此上下文中為主線程)是否已被中斷。由于主線程從未被中斷過,所以打印的結(jié)果是兩個false。

如何讓主線程產(chǎn)生中斷效果

public class Run2 {
    public static void main(String args[]){
        Thread.currentThread().interrupt();
        System.out.println("stop 1??" + Thread.interrupted());
        System.out.println("stop 2??" + Thread.interrupted());

        System.out.println("End");
    }
}
/*
------------------
結(jié)果:
stop 1??true
stop 2??false
End
*/

第二個值是 false,因為根據(jù) Interrupted() 方法的官方文檔,它會檢測當(dāng)前線程(在這里就是主線程)的中斷狀態(tài),它會在調(diào)用時清除線程的中斷狀態(tài)。

換句話說,如果連續(xù)調(diào)用它,第二次調(diào)用返回 false,因為它已經(jīng)清除了第一次調(diào)用設(shè)置的中斷狀態(tài)。

因此,如果連續(xù)調(diào)用interrupted()兩次,第二次調(diào)用將返回false,因為第一次調(diào)用清除了線程的中斷狀態(tài)。

isInterrupted()

現(xiàn)在讓我們看一下 isInterrupted() 方法。

public class Run3 {
    public static void main(String args[]){
        Thread thread = new MyThread();
        thread.start();
        thread.interrupt();
        System.out.println("stop 1??" + thread.isInterrupted());
        System.out.println("stop 2??" + thread.isInterrupted());
    }
}
/*
---------------
結(jié)果:
stop 1??true
stop 2??true
*/

isInterrupted() 不會清除中斷狀態(tài),這就是為什么在輸出中看到兩個true。

使用異常來停止線程

有了上面獲得的知識,就可以在線程中使用for循環(huán)來檢查線程是否處于停止?fàn)顟B(tài)。 如果處于停止?fàn)顟B(tài),后續(xù)的代碼將不再運行。

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 500000; i++) {
            if (Thread.interrupted()) {
                System.out.println("Thread is interrupted. Exiting...");
                return; //退出
            }
            System.out.println("i="+(i+1));
        }
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
        try {
            Thread.sleep(2000);
            thread.interrupt(); // 設(shè)置中斷狀態(tài)
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/*
-------------
結(jié)果:
...
i=202053
i=202054
i=202055
i=202056
Thread is interrupted. Exiting...
*/

在停止線程的同時,將繼續(xù)執(zhí)行 for 循環(huán)之后的任何代碼。

改下代碼,讓我們看一下下面的例子:

public class MyThread extends Thread {
    public void run(){
        super.run();
        for(int i=0; i<500000; i++){
            if(this.interrupted()) {
                System.out.println("Thread is interrupted. Exiting...");
                break;
            }
            System.out.println("i="+(i+1));
        }

        System.out.println("Out of for");
    }
}
/*
結(jié)果:
...
i=180136
i=180137
i=180138
i=180139
Thread is interrupted. Exiting...
Out of for
*/

如何解決中斷后,代碼繼續(xù)執(zhí)行的問題

public class MyThread extends Thread {
    public void run(){
        super.run();
        try {
            for(int i=0; i< 500000; i++){
                if(this.interrupted()) {
                    System.out.println("Thread is interrupted. Exiting...");
                    throw new InterruptedException();
                }
                System.out.println("i="+(i+1));
            }

            System.out.println("Out of for");
        } catch (InterruptedException e) {
            System.out.println("In catch...");
            e.printStackTrace();
        }
    }
}
/*
--------------------------------------------------------------------------
結(jié)果:
...
i=203798
i=203799
i=203800
Thread is interrupted. Exiting...
In catch...
java.lang.InterruptedException
 at thread.MyThread.run(MyThread.java:13)
*/

線程Sleep怎么停止

如果線程在 sleep() 狀態(tài)下停止會有什么影響?

public class MyThread extends Thread {
    public void run(){
        super.run();

        try {
            System.out.println("Thread begin...");
            Thread.sleep(200000);
            System.out.println("Thread end...");
        } catch (InterruptedException e) {
            System.out.println("Stop while sleeping" + this.isInterrupted());
            e.printStackTrace();
        }
    }
}
/*
-----------------------------------------------------------------------
 結(jié)果:
Thread begin...
Stop while sleeping,the result of isInterrupted() is::false
java.lang.InterruptedException: sleep interrupted
 at java.lang.Thread.sleep(Native Method)
 at thread.MyThread.run(MyThread.java:12)
*/

從打印結(jié)果來看,如果線程在睡眠狀態(tài)下停止,它將拋出InterruptedException異常進(jìn)入catch塊并清除停止?fàn)顟B(tài)值,將其設(shè)置為false。

強(qiáng)制停止線程

使用 stop() 方法終止線程是一種非常激進(jìn)的方法。

public class MyThread extends Thread {
    private int i = 0;
    public void run(){
        super.run();
        try {
            while (true){
                System.out.println("i=" + i);
                i++;
                Thread.sleep(200);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class Run {
    public static void main(String args[]) throws InterruptedException {
        Thread thread = new MyThread();
        thread.start();
        Thread.sleep(2000);
        thread.stop();
    }
}
/*
-----------------------------------------------
  結(jié)果:
i=0
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9

Process finished with exit code 0
*/

當(dāng)調(diào)用 stop() 方法時,它會拋出 java.lang.ThreadDeath 異常,但大多數(shù)情況下,不需要顯式捕獲該異常。

public class MyThread extends Thread {
    private int i = 0;
    public void run(){
        super.run();
        try {
            this.stop();
        } catch (ThreadDeath e) {
            System.out.println("In catch");
            e.printStackTrace();
        }
    }
}

public class Run {
    public static void main(String args[]) throws InterruptedException {
        Thread thread = new MyThread();
        thread.start();
    }
}

stop() 方法已被棄用,因為強(qiáng)制停止線程可能會阻止某些必要的清理工作完成。

此外,它還可能導(dǎo)致鎖定對象解鎖,從而導(dǎo)致數(shù)據(jù)同步問題和數(shù)據(jù)不一致問題。 由

于 stop() 方法在 JDK 中已被標(biāo)記為已棄用/過時,因此很明顯它存在功能缺陷。 因此,不建議在程序中使用 stop() 方法。

使用 return 來停止線程

將interrupt()方法與return結(jié)合起來也可以達(dá)到停止線程的效果。

public class MyThread extends Thread {
    public void run(){
        while (true){
            if(this.isInterrupted()){
                System.out.println("The thread has been stopped.");
                return;
            }
            System.out.println("Time: " + System.currentTimeMillis());
        }
    }
}

public class Run {
    public static void main(String args[]) throws InterruptedException {
        Thread thread = new MyThread();
        thread.start();
        Thread.sleep(2000);
        thread.interrupt();
    }
}
/*
------------------------------------
結(jié)果:...
Time: 1696990194000
Time: 1696990194000
Time: 1696990194000
The thread has been stopped.
*/

但是,仍然建議使用“拋出異常”方法來停止線程,因為它允許您通過在 catch 塊中重新拋出異常來傳播停止事件。

到此這篇關(guān)于Java實現(xiàn)優(yōu)雅停止線程的有效方法詳解的文章就介紹到這了,更多相關(guān)Java停止線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MyBatis中映射文件的使用案例代碼

    MyBatis中映射文件的使用案例代碼

    這篇文章主要介紹了MyBatis中映射文件的使用,本文結(jié)合實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-02-02
  • Java實現(xiàn)簡易學(xué)生管理系統(tǒng)

    Java實現(xiàn)簡易學(xué)生管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)簡易學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Spring 4.1+JSONP的使用指南

    Spring 4.1+JSONP的使用指南

    在解釋JSONP之前,我們需要了解下”同源策略“,這對理解跨域有幫助?;诎踩脑?瀏覽器是存在同源策略機(jī)制的,同源策略阻止從一個源加載的文檔或腳本獲取或設(shè)置另一個源加載額文檔的屬性。說的簡單點就是瀏覽器限制腳本只能和同協(xié)議、同域名、同端口的腳本進(jìn)行交互。
    2016-04-04
  • Java?深入理解創(chuàng)建型設(shè)計模式之抽象工廠模式

    Java?深入理解創(chuàng)建型設(shè)計模式之抽象工廠模式

    當(dāng)系統(tǒng)所提供的工廠所需生產(chǎn)的具體產(chǎn)品并不是一個簡單的對象,而是多個位于不同產(chǎn)品等級結(jié)構(gòu)中屬于不同類型的具體產(chǎn)品時需要使用抽象工廠模式,抽象工廠模式是所有形式的工廠模式中最為抽象和最具一般性的一種形態(tài)
    2022-02-02
  • java使用鏈表實現(xiàn)約瑟夫環(huán)

    java使用鏈表實現(xiàn)約瑟夫環(huán)

    這篇文章主要為大家詳細(xì)介紹了java使用鏈表實現(xiàn)約瑟夫環(huán),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 解決@PostConstruct注解導(dǎo)致的程序無法啟動(@PostConstruct的執(zhí)行)

    解決@PostConstruct注解導(dǎo)致的程序無法啟動(@PostConstruct的執(zhí)行)

    這篇文章主要介紹了解決@PostConstruct注解導(dǎo)致的程序無法啟動(@PostConstruct的執(zhí)行)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Spring?Boot整合持久層之JdbcTemplate多數(shù)據(jù)源

    Spring?Boot整合持久層之JdbcTemplate多數(shù)據(jù)源

    持久層是JavaEE中訪問數(shù)據(jù)庫的核心操作,SpringBoot中對常見的持久層框架都提供了自動化配置,例如JdbcTemplate、JPA 等,MyBatis 的自動化配置則是MyBatis官方提供的。接下來分別向讀者介紹Spring Boot整合這持久層技術(shù)中的整合JdbcTemplate
    2022-08-08
  • Java?NIO?中?Selector?解析

    Java?NIO?中?Selector?解析

    這篇文章主要介紹了Java?NIO?中?Selector,Selector即選擇器,選擇器提供選擇執(zhí)行已經(jīng)就緒的任務(wù)的能力即為翻譯為多路復(fù)用,下面文章對Selector詳細(xì)介紹內(nèi)容,需要的小伙伴可以參考一下
    2022-02-02
  • 使用jmeter實現(xiàn)對jar包的調(diào)用方式

    使用jmeter實現(xiàn)對jar包的調(diào)用方式

    這篇文章主要介紹了使用jmeter實現(xiàn)對jar包的調(diào)用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • Spring如何使用xml創(chuàng)建bean對象

    Spring如何使用xml創(chuàng)建bean對象

    這篇文章主要介紹了Spring如何使用xml創(chuàng)建bean對象,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08

最新評論