最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實現中斷線程算法的代碼詳解

 更新時間:2025年08月01日 10:54:15   作者:Katie。  
在多線程編程中,線程的創(chuàng)建、運行和終止是并發(fā)控制的核心,Java 提供了 Thread.interrupt() 與 InterruptedException 機制,允許線程之間通過中斷標志進行協調,本項目將以Java 實現線程中斷算法為主題,深度剖析中斷機制原理,需要的朋友可以參考下

一、項目背景詳細介紹

在多線程編程中,線程的創(chuàng)建、運行和終止是并發(fā)控制的核心。Java 提供了 Thread.interrupt()InterruptedException 機制,允許線程之間通過“中斷標志”進行協調,優(yōu)雅地請求某個線程停止其當前或未來的工作。但實際開發(fā)中,許多初學者對中斷機制存在誤解:

  • 誤以為調用 interrupt() 即可強制終止線程;
  • 忽略 InterruptedException,導致中斷信號被吞噬;
  • 未在業(yè)務循環(huán)或阻塞調用中及時檢查中斷狀態(tài)。

正確使用線程中斷不僅能避免強制停止帶來的資源不一致,還能讓線程根據業(yè)務需要決定退出時機,實現“可控關閉”與“快速響應”并發(fā)任務終止請求。本項目將以“Java 實現線程中斷算法”為主題,深度剖析中斷機制原理,構建多種場景演示,幫助大家系統(tǒng)掌握如何優(yōu)雅地中斷線程及應對常見陷阱。

二、項目需求詳細介紹

核心功能

演示如何在:

  • 忙循環(huán) 中檢查并響應中斷;
  • 阻塞調用Thread.sleepObject.wait、BlockingQueue.take 等)中捕獲并處理 InterruptedException
  • I/O 操作InputStream.read)中響應中斷;

提供一個通用的 InterruptibleTask 抽象類,封裝中斷檢查和資源清理框架,子類只需實現 doWork() 方法。

實現一個 ThreadInterrupter 工具類,用于啟動、監(jiān)控并中斷測試線程,打印終止流程日志。

支持以下場景:

  • 無限循環(huán)任務:立即退出;
  • 周期性任務:在循環(huán)中定時調用 sleep 并響應中斷;
  • 阻塞隊列任務:從 LinkedBlockingQueue 中取數據,被 interrupt() 時拋出 InterruptedException
  • I/O 讀線程:阻塞在 read(),調用 close()interrupt() 時退出。

性能需求

  • 各種場景中斷響應時間在毫秒級;
  • 中斷處理邏輯對業(yè)務無明顯額外開銷。

接口設計

public abstract class InterruptibleTask implements Runnable {
    protected volatile boolean stopped = false;
    protected abstract void doWork() throws Exception;
    protected void cleanup() { /* 資源清理 */ }
    @Override
    public void run() {
        try { while (!stopped) doWork(); }
        catch (InterruptedException ie) { Thread.currentThread().interrupt(); }
        catch (Exception e) { e.printStackTrace(); }
        finally { cleanup(); }
    }
    public void stop() { stopped = true; }
}

以及

public class ThreadInterrupter {
    public static void interruptAndJoin(Thread t, long timeoutMs);
}

異常處理

  • InterruptedException 必須捕獲并正確恢復中斷標志;
  • 其他業(yè)務異常在 run 中打印或記錄,不阻塞終止流程。

測試用例

  • 啟動多種 InterruptibleTask,延遲一定時間后調用 thread.interrupt() 和/或 task.stop(),觀察日志輸出,驗證線程正常退出。

三、相關技術詳細介紹

中斷原理

  • Thread.interrupt():設置目標線程的中斷標志位;

被阻塞 的線程(在 sleep、wait、join、BlockingQueue 等)將立即拋出 InterruptedException,并清除中斷標志;

非阻塞 的線程需自行調用 Thread.interrupted()Thread.currentThread().isInterrupted() 檢查標志;

正確做法是在捕獲 InterruptedException 后調用 Thread.currentThread().interrupt() 恢復中斷狀態(tài),以便上層或后續(xù)業(yè)務繼續(xù)檢測。

Java 阻塞 API

  • Thread.sleep(long ms)
  • Object.wait()wait(timeout)
  • Thread.join()join(timeout)
  • BlockingQueue.puttake
  • Selector.select() 等 NIO 阻塞

I/O 中斷

  • Java NIO 通道(InterruptibleChannel)在中斷時會關閉通道并拋出 ClosedByInterruptException
  • 老式 I/O (InputStream.read) 不響應 interrupt(),需另外調用 close();

資源清理

  • finally 塊中關閉流、釋放鎖、取消注冊,避免泄漏;

四、實現思路詳細介紹

抽象任務框架

定義 InterruptibleTask

  • stopped 標志配合 interrupt() 使用,可主動通知終止;
  • doWork() 子類實現具體業(yè)務,可拋出 InterruptedException;
  • cleanup() 提供資源釋放鉤子。

工具類

ThreadInterrupter.interruptAndJoin(Thread, timeout)

  • 調用 t.interrupt();
  • t.join(timeout)
  • 如果仍存活,可打印警告或調用 stop()

示例場景

  • BusyLoopTask:在循環(huán)中定期調用 Thread.sleep(100) 以模擬工作,可迅速響應中斷;
  • BlockingQueueTask:在 take() 上阻塞,interrupt()thread.interrupt() 將使其拋出 InterruptedException;
  • IOReadTask:使用 PipedInputStreamPipedOutputStream 演示傳統(tǒng) I/O,在中斷時調用 close()

監(jiān)控與日志

  • 每個任務在 run 開始和結束時打印日志;
  • 工具類在中斷和 join 后打印狀態(tài);

五、完整實現代碼

// 文件:InterruptibleTask.java
package com.example.threadinterrupt;
 
public abstract class InterruptibleTask implements Runnable {
    // 可選的主動停止標志
    protected volatile boolean stopped = false;
 
    /** 子類實現具體工作邏輯,支持拋出 InterruptedException */
    protected abstract void doWork() throws Exception;
 
    /** 資源清理(流/鎖/注冊等),可由子類覆蓋 */
    protected void cleanup() { }
 
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.printf("[%s] 開始執(zhí)行%n", name);
        try {
            while (!stopped && !Thread.currentThread().isInterrupted()) {
                doWork();
            }
        } catch (InterruptedException ie) {
            // 恢復中斷狀態(tài),允許外層檢測
            Thread.currentThread().interrupt();
            System.out.printf("[%s] 捕獲 InterruptedException,準備退出%n", name);
        } catch (Exception e) {
            System.err.printf("[%s] 出現異常: %s%n", name, e);
            e.printStackTrace();
        } finally {
            cleanup();
            System.out.printf("[%s] 已退出%n", name);
        }
    }
 
    /** 主動請求停止(可選) */
    public void stop() {
        stopped = true;
    }
}
 
// ----------------------------------------------------------------
// 文件:ThreadInterrupter.java
package com.example.threadinterrupt;
 
public class ThreadInterrupter {
    /**
     * 中斷線程并等待退出
     * @param t         目標線程
     * @param timeoutMs 等待退出超時時間(毫秒)
     */
    public static void interruptAndJoin(Thread t, long timeoutMs) {
        System.out.printf("[Interrupter] 中斷線程 %s%n", t.getName());
        t.interrupt();
        try {
            t.join(timeoutMs);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        if (t.isAlive()) {
            System.err.printf("[Interrupter] 線程 %s 未能在 %d ms 內退出%n",
                    t.getName(), timeoutMs);
        } else {
            System.out.printf("[Interrupter] 線程 %s 已退出%n", t.getName());
        }
    }
}
 
// ----------------------------------------------------------------
// 文件:BusyLoopTask.java
package com.example.threadinterrupt;
 
public class BusyLoopTask extends InterruptibleTask {
    private int counter = 0;
    @Override
    protected void doWork() throws InterruptedException {
        // 模擬業(yè)務:每100ms自增一次
        Thread.sleep(100);
        System.out.printf("[BusyLoop] %s:計數 %d%n",
                Thread.currentThread().getName(), ++counter);
    }
}
 
// ----------------------------------------------------------------
// 文件:BlockingQueueTask.java
package com.example.threadinterrupt;
 
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
 
public class BlockingQueueTask extends InterruptibleTask {
    private final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
 
    public BlockingQueueTask() {
        // 先放一個元素供 take
        queue.offer("初始數據");
    }
 
    @Override
    protected void doWork() throws InterruptedException {
        String data = queue.take();  // 阻塞等待
        System.out.printf("[BlockingQueue] %s:取到數據 %s%n",
                Thread.currentThread().getName(), data);
    }
}
 
// ----------------------------------------------------------------
// 文件:IOReadTask.java
package com.example.threadinterrupt;
 
import java.io.*;
 
public class IOReadTask extends InterruptibleTask {
    private PipedInputStream in;
    private PipedOutputStream out;
 
    public IOReadTask() throws IOException {
        in = new PipedInputStream();
        out = new PipedOutputStream(in);
        // 啟動寫線程,模擬持續(xù)寫入
        new Thread(() -> {
            try {
                int i = 0;
                while (true) {
                    out.write(("msg" + i++ + "\n").getBytes());
                    Thread.sleep(200);
                }
            } catch (Exception ignored) { }
        }, "Writer").start();
    }
 
    @Override
    protected void doWork() throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line = reader.readLine(); // 阻塞在 readLine
        System.out.printf("[IORead] %s:讀到 %s%n",
                Thread.currentThread().getName(), line);
    }
 
    @Override
    protected void cleanup() {
        try { in.close(); out.close(); } catch (IOException ignored) { }
        System.out.printf("[IORead] %s:已關閉流%n", Thread.currentThread().getName());
    }
}
 
// ----------------------------------------------------------------
// 文件:Main.java
package com.example.threadinterrupt;
 
public class Main {
    public static void main(String[] args) throws Exception {
        // 創(chuàng)建并啟動任務
        BusyLoopTask busy = new BusyLoopTask();
        Thread t1 = new Thread(busy, "BusyLoop-Thread");
        t1.start();
 
        BlockingQueueTask bq = new BlockingQueueTask();
        Thread t2 = new Thread(bq, "BlockingQueue-Thread");
        t2.start();
 
        IOReadTask io = new IOReadTask();
        Thread t3 = new Thread(io, "IORead-Thread");
        t3.start();
 
        // 運行 2 秒后中斷
        Thread.sleep(2000);
        ThreadInterrupter.interruptAndJoin(t1, 500);
        ThreadInterrupter.interruptAndJoin(t2, 500);
        ThreadInterrupter.interruptAndJoin(t3, 500);
    }
}

六、代碼詳細解讀

InterruptibleTask

統(tǒng)一在 run() 中檢查 stoppedisInterrupted();

catch (InterruptedException) 中調用 Thread.currentThread().interrupt() 恢復中斷標志;

finally 中調用 cleanup(),保證資源釋放。

ThreadInterrupter.interruptAndJoin

  • 調用 thread.interrupt() 發(fā)送中斷請求;
  • join(timeout) 等待指定時間;
  • 根據 isAlive() 判斷線程是否已退出并打印日志。

BusyLoopTask

  • 每 100ms sleep 后打印計數,sleep 拋中斷時捕獲并退出循環(huán)。

BlockingQueueTask

  • queue.take() 上阻塞,收到中斷時 take()InterruptedException,退出循環(huán)。

IOReadTask

  • 使用 PipedInputStream/PipedOutputStream 模擬阻塞 I/O;
  • readLine() 上阻塞,收到中斷后通過 in.close() 觸發(fā) IOException 或 NIO 異常,退出。
  • cleanup() 中關閉流,避免資源泄漏。

Main

  • 啟動三種任務,運行 2 秒后統(tǒng)一中斷并等待退出,觀察日志驗證各自的中斷響應時機與清理邏輯。

七、項目詳細總結

通過本項目的示例,我們對 Java 線程中斷機制有了更系統(tǒng)的理解:

  • interrupt() 只發(fā)出中斷請求,不強制殺死線程;
  • 阻塞非阻塞 場景的中斷響應方式不同,必須根據 API 特性在代碼中主動檢查或捕獲 InterruptedException;
  • 正確的中斷處理需在 catch 中恢復中斷標志,并在 finally 中釋放資源;
  • 構建通用的 InterruptibleTask 抽象框架,可以極大簡化業(yè)務開發(fā),實現高復用。

八、項目常見問題及解答

Q:interrupt()stop() 的區(qū)別?
Astop() 已廢棄,會強制釋放鎖,可能導致數據不一致;interrupt() 是協作式,不破壞資源一致性。

Q:為什么要在 catch 中調用 Thread.currentThread().interrupt()
AInterruptedException 拋出后中斷標志被清除,需恢復以便后續(xù)或上層代碼繼續(xù)檢測。

Q:傳統(tǒng) I/O(InputStream.read)會響應中斷嗎?
A:不會。需要在另一個線程調用 close() 來使其拋出異常,或使用 NIO 通道。

Q:如何優(yōu)雅停止長期阻塞的 NIO Selector.select()?
A:可調用 selector.wakeup() 或關閉 Selector,而非 interrupt()。

Q:中斷后任務如何保證冪等?
A:在 cleanup() 中需考慮業(yè)務重入與狀態(tài)回滾,避免部分操作執(zhí)行兩次。

九、擴展方向與性能優(yōu)化

  • 更多阻塞 API:演示 ReentrantLock.lockInterruptibly()CountDownLatch.await()、Semaphore.acquire() 等場景下中斷響應;
  • 線程池中斷:結合 ThreadPoolExecutor.shutdownNow()Future.cancel(true) 進行批量中斷;
  • 自定義中斷策略:支持“優(yōu)雅關閉”與“強制關閉”兩種模式,讓調用者按需選擇;
  • 監(jiān)控集成:將中斷日志與 JMX 或 Prometheus 指標結合,實時觀察線程退出率與健康狀態(tài);
  • 中斷回調:為任務提供回調接口,在線程被中斷時自動執(zhí)行特定邏輯(如狀態(tài)上報、補償操作);
  • 庫化發(fā)布:將上述框架封裝為 Maven 坐標,可在多個項目中復用,減少重復工作。

以上就是Java實現中斷線程算法的代碼詳解的詳細內容,更多關于Java中斷線程算法的資料請關注腳本之家其它相關文章!

相關文章

  • Spring Security更換加密方式的完整方案

    Spring Security更換加密方式的完整方案

    隨著現在對軟件系統(tǒng)安全性要求的越來越嚴苛,對于很多項目,升級密碼都是勢在必行的,若項目使用Spring Security框架,只需稍作修改,便可達到更換加密方式,所以本文給大家介紹了Spring Security更換加密方式的完整方案,需要的朋友可以參考下
    2025-12-12
  • 如何重寫hashcode和equals方法

    如何重寫hashcode和equals方法

    這篇文章主要介紹了如何重寫hashcode和equals方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Spring與Redis集成的正確方式流程詳解

    Spring與Redis集成的正確方式流程詳解

    這篇文章主要為大家介紹了Spring與Redis集成的正確方式流程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • Java Spring AOP之PointCut案例詳解

    Java Spring AOP之PointCut案例詳解

    這篇文章主要介紹了Java Spring AOP之PointCut案例詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-09-09
  • JUC系列學習工具類CountDownLatch詳解

    JUC系列學習工具類CountDownLatch詳解

    這篇文章主要介紹了JUC系列學習工具類CountDownLatch詳解,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可任意參考一下
    2022-08-08
  • maven關于pom文件中的relativePath標簽使用

    maven關于pom文件中的relativePath標簽使用

    在Maven項目中,子工程通過<relativePath>標簽指定父工程的pom.xml位置,以確保正確繼承父工程的配置,這個標簽可以配置為默認值、空值或自定義值,默認情況下,Maven會向上一級目錄尋找父pom;若配置為空值
    2024-09-09
  • Java 入門圖形用戶界面設計之單選按鈕

    Java 入門圖形用戶界面設計之單選按鈕

    圖形界面(簡稱GUI)是指采用圖形方式顯示的計算機操作用戶界面。與早期計算機使用的命令行界面相比,圖形界面對于用戶來說在視覺上更易于接受,本篇精講Java語言中關于圖形用戶界面的單選按鈕
    2022-02-02
  • Java?Mybatis框架由淺入深全解析上篇

    Java?Mybatis框架由淺入深全解析上篇

    MyBatis是一個優(yōu)秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發(fā)者只需要關注SQL本身,而不需要花費精力去處理例如注冊驅動、創(chuàng)建connection、創(chuàng)建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼本文將為大家初步的介紹一下MyBatis的使用
    2022-07-07
  • 基于jenkins構建結果企業(yè)微信提醒

    基于jenkins構建結果企業(yè)微信提醒

    這篇文章主要介紹了基于jenkins構建結果企業(yè)微信提醒,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • Java設計模式之模版方法模式簡介

    Java設計模式之模版方法模式簡介

    這篇文章主要介紹了Java設計模式之模版方法模式,需要的朋友可以參考下
    2014-07-07

最新評論

开远市| 铜梁县| 和政县| 托里县| 梅州市| 方正县| 文水县| 洛阳市| 渭南市| 綦江县| 文登市| 措勤县| 禄劝| 田林县| 朝阳区| 嫩江县| 荥经县| 南丹县| 镇康县| 宕昌县| 武强县| 双桥区| 甘孜县| 乐安县| 赤城县| 剑川县| 崇阳县| 渝北区| 同江市| 平果县| 黄梅县| 屏南县| 枣强县| 宜丰县| 屏山县| 沙洋县| 桐庐县| 天峨县| 且末县| 花垣县| 建宁县|