亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java 正確終止線程的方法

 更新時間:2020年12月02日 10:12:05   作者:yuanyb  
這篇文章主要介紹了Java 正確終止線程的方法,幫助大家更好的理解和學(xué)習(xí)java 多線程的相關(guān)知識,感興趣的朋友可以了解下

Thread類中有一個已經(jīng)廢棄的 stop() 方法,它可以終止線程,但由于它不管三七二十一,直接終止線程,所以被廢棄了。比如,當線程被停止后還需要進行一些善后操作(如,關(guān)閉外部資源),使用這個方法就無能為力了??梢酝ㄟ^線程中斷來實現(xiàn)線程終止。

首先來看一下Java線程中斷的一些內(nèi)容:

  • Java平臺為每個線程維護了一個布爾型的中斷標記,可以通過下列方法獲取該標記的值:

            interrupt() 中斷某個線程
            isInterrupted() 返回該線程的中斷標記
            interrupted() 返回并重置該線程的中斷標記(置為false)

  • 中斷僅是發(fā)起線程對目標線程的一種請求,也就是說,目標線程對這種請求可以相應(yīng),也可以忽略。
  • Java標準庫中與線程阻塞相關(guān)的方法對中斷的相應(yīng)方式都是拋出 InterruptedException 異常,并且按照慣例,拋出異常前都會重置中斷標記為false,因此這些方法會清空線程的中斷標記。
  • Java標準庫中與線程阻塞相關(guān)的方法在進行阻塞前會判斷中斷標記是否為true,為true則拋出異常;如果在阻塞后調(diào)用中斷方法的話,那么JVM會設(shè)置該線程的中斷標記,然后將該線程喚醒,因此中斷具有喚醒線程的作用。

由上面幾點和第二句加粗的話可知,可以使用線程中斷來實現(xiàn)線程終止,只要目標線程判斷一下中斷標記即可,即使被中斷的線程正處于阻塞狀態(tài),也能把他喚醒起來終止;由第一句加粗的話可知,直接使用線程中斷實現(xiàn)線程終止是存在風(fēng)險的,因為可能調(diào)用了一些Java標準庫的阻塞方法,而導(dǎo)致了中斷標記被清空,也就無法獲得中斷標記了(總是false),因此需要自己創(chuàng)建一個中斷標記配合使用。

如,下面是一個可中斷的任務(wù)執(zhí)行器,他會在每次執(zhí)行任務(wù)前,判斷一下自定i的終止標記和剩余的任務(wù)數(shù)(善后);提供的shutdown方法除了將工作線程中斷外(主要作用是喚醒可能處于阻塞狀態(tài)的任務(wù)),還會將終止交集 terminated 置為 true。

執(zhí)行 main 方法,可以發(fā)現(xiàn),首先會打印出“客戶端調(diào)用了 shutdown 方法”,然后過了四秒,main線程才會終止,可知shutdown方法正確地將目標線程終止了。關(guān)于“按照慣例,Java標準庫中拋出InterruptedException異常的和線程相關(guān)的阻塞方法會清空中斷標記”,可以將條件中的 !interminated 替換成 !Thread.currentThread().isInterrupted(),然后再執(zhí)行main方法測試,可以發(fā)現(xiàn)main線程始終無法終止,因為 sleep() 方法清空了中斷標記,所以  !Thread.currentThread().isInterrupted() 始終為true,導(dǎo)致工作線程始終無法終止。

public class TerminableTaskRunner {
    // 存儲要執(zhí)行的任務(wù)
    private final BlockingQueue<Runnable> tasks;
    // 線程終止標志
    private volatile boolean terminated;
    // 剩余的任務(wù)數(shù)
    private final AtomicInteger count;
    // 實際執(zhí)行任務(wù)的線程
    private volatile Thread workThread;
 
    public TerminableTaskRunner(int capacity) {
        this.tasks = new LinkedBlockingDeque<>(capacity);
        this.count = new AtomicInteger(0);
        this.workThread = new WorkThread();
        workThread.start();
    }
 
    public void submit(Runnable task) {
        this.tasks.add(task);
        this.count.incrementAndGet();
    }
 
    public void shutdown() {
        terminated = true; // 線程終止標志,由于中斷標志可能會被覆蓋,所以需要自己創(chuàng)建一個標志
        if (workThread != null)
            workThread.interrupt(); // 喚醒線程
    }
 
    private class WorkThread extends Thread {
        @Override
        public void run() {
            Runnable task;
            try {
                while (!terminated || tasks.size() >= 1) {
                    task = tasks.take();
                    try {
                        task.run(); // 可能會清空當前線程的中斷標記,如task.run()在內(nèi)部調(diào)用的阻塞方法拋出了InterruptedException
                    } catch (Throwable e) {
                        e.printStackTrace();
                    }
                    count.decrementAndGet();
                }
            } catch (InterruptedException e) {
                // 一旦調(diào)用shutdown且tasks.take()阻塞住,就拋出該異常,沒有任務(wù)要執(zhí)行,直接終止
                workThread = null;
            }
        }
    }
 
    public static void main(String[] args) {
        TerminableTaskRunner taskRunner = new TerminableTaskRunner(4);
        for (int i = 0; i < 4; i++) {
            taskRunner.submit(()->{
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    System.out.println("客戶端調(diào)用了 shutdown 方法");
                }
            });
        }
        taskRunner.shutdown();
 
    }
}

以上就是Java 正確終止線程的方法的詳細內(nèi)容,更多關(guān)于Java 終止線程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 通過JDK源碼學(xué)習(xí)InputStream詳解

    通過JDK源碼學(xué)習(xí)InputStream詳解

    InputStream抽象類是所有字節(jié)輸入流的類的超類。這篇文章主要給大家介紹了關(guān)于通過JDK源碼學(xué)習(xí)InputStream的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11
  • 詳解springboot + profile(不同環(huán)境讀取不同配置)

    詳解springboot + profile(不同環(huán)境讀取不同配置)

    本篇文章主要介紹了springboot + profile(不同環(huán)境讀取不同配置),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Java Web Fragment在項目中使用方法詳解

    Java Web Fragment在項目中使用方法詳解

    這篇文章主要介紹了Web Fragment在項目中使用方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • springboot多模塊多環(huán)境配置文件問題(動態(tài)配置生產(chǎn)和開發(fā)環(huán)境)

    springboot多模塊多環(huán)境配置文件問題(動態(tài)配置生產(chǎn)和開發(fā)環(huán)境)

    這篇文章主要介紹了springboot多模塊多環(huán)境配置文件問題(動態(tài)配置生產(chǎn)和開發(fā)環(huán)境),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Spring框架基于AOP實現(xiàn)簡單日志管理步驟解析

    Spring框架基于AOP實現(xiàn)簡單日志管理步驟解析

    這篇文章主要介紹了Spring框架基于AOP實現(xiàn)簡單日志管理步驟解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • 去掉 IDEA 中 mybatis配置文件的局部背景顏色(圖解)

    去掉 IDEA 中 mybatis配置文件的局部背景顏色(圖解)

    這篇文章通過圖文并茂的形式給大家介紹了去掉IntelliJ IDEA 中 mybatis配置文件的局部背景顏色及mybatis 對應(yīng)的 xml 文件警告的方法圖解,需要的朋友可以參考下
    2018-09-09
  • Java鍵值對Pair的使用方式和操作實現(xiàn)

    Java鍵值對Pair的使用方式和操作實現(xiàn)

    鍵值對是一種常見的數(shù)據(jù)結(jié)構(gòu),它由一個唯一的鍵和與之關(guān)聯(lián)的值組成,本文就來介紹一下Java鍵值對Pair的使用方式和操作實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • Java中簡單實用Quartz概述

    Java中簡單實用Quartz概述

    Quartz是一個開源的Java調(diào)度框架,可以用來實現(xiàn)在指定的時間或時間間隔觸發(fā)任務(wù)執(zhí)行的功能,這篇文章主要介紹了Java中簡單實用Quartz,需要的朋友可以參考下
    2023-02-02
  • java中的transient關(guān)鍵字解讀

    java中的transient關(guān)鍵字解讀

    這篇文章主要介紹了java中的transient關(guān)鍵字解讀,transient關(guān)鍵字的主要作用就是讓某些被transient關(guān)鍵字修飾的成員屬性變量不被序列化,實際上也正是因此,在學(xué)習(xí)過程中很少用得上序列化操作,一般都是在實際開發(fā)中,需要的朋友可以參考下
    2023-09-09

最新評論