成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一文學會終止線程的兩種方式

開發 前端
雖然本文主題是終止線程,但其實可以推廣到所有while(true)的場景中。在可能出現死循環或者有條件的大循環中,我們都應該適當的增加標記位,可以快速終止循環。

你好,我是看山。

在Java中,終止一個線程(Kill a Thread)還是有一定技巧的,本文提供兩種方式。

一、使用標志位

我們先創建一個線程類,run方法循環執行一些邏輯,永遠不會終止,且不會自行結束。為了服務的穩定,我們需要一種方法停止線程。

本節給出標志位法,簡單說就是,有一個原子標志位,可以用來標記當前循環是否執行,如果不可執行,則跳出循環,當前線程即結束。

public class ControlSubThread extends Thread {
    private final AtomicBoolean running = new AtomicBoolean(false);
    private final AtomicBoolean stopped = new AtomicBoolean(true);
    private final int interval;
    private final AtomicInteger count = new AtomicInteger(0);

    public ControlSubThread(int sleepInterval) {
        interval = sleepInterval;
    }

    @Override
    public void start() {
        Thread worker = new Thread(this);
        worker.start();
    }

    public void shutdown() {
        running.set(false);
        System.out.println("線程正在關閉,當前count為:" + count.get());
    }

    @Override
    public void run() {
        running.set(true);
        stopped.set(false);
        while (running.get()) {
            try {
                System.out.println("線程正在運行(" + System.currentTimeMillis() / 1000 + "): " + count.incrementAndGet());
                Thread.sleep(interval);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("線程被中斷,操作未能完成");
            }
            // 在此處執行一些操作
        }
        stopped.set(true);
    }
}

我們在while循環使用了一個AtomicBoolean,通過控制這個標志位的true或false來啟動或終止循環。循環終止了,線程自然也就結束了。

而且需要注意,考慮到JMM,標志位一定要被volatile定義的,為了簡答,我們這里選擇了AtomicBoolean作為標志位。

我們看下應用:

final ControlSubThread thread = new ControlSubThread(1000);
thread.start();

System.out.println("主線程等待");
TimeUnit.SECONDS.sleep(10);

thread.shutdown();
thread.join();
System.out.println("主線程終止");

運行結果為:

主線程等待 線程正在運行(1733318881): 1 線程正在運行(1733318882): 2 線程正在運行(1733318883): 3 線程正在運行(1733318884): 4 線程正在運行(1733318885): 5 線程正在運行(1733318886): 6 線程正在運行(1733318887): 7 線程正在運行(1733318888): 8 線程正在運行(1733318889): 9 線程正在運行(1733318890): 10 線程正在關閉,當前count為:10 主線程終止

二、中斷線程

上面的實現方式會存在一種問題,如果sleep()方法時間過長,或者運行過程出現死鎖,永遠不會執行到下一次判斷,那將長時間阻塞后者無法清除線程。

這個時候我們可以使用interrupt()方法,我們對上面的示例稍加改造:

public class InterruptSubThread extends Thread {
    private final AtomicBoolean running = new AtomicBoolean(false);
    private final AtomicBoolean stopped = new AtomicBoolean(true);
    private final int interval;
    private final Thread worker;
    private final AtomicInteger count = new AtomicInteger(0);

    public InterruptSubThread(int sleepInterval) {
        interval = sleepInterval;
        worker = new Thread(this);
    }

    @Override
    public void start() {
        worker.start();
    }

    public void shutdown() {
        running.set(false);
    }

    @Override
    public void interrupt() {
        running.set(false);
        worker.interrupt();
    }

    @Override
    public void run() {
        running.set(true);
        stopped.set(false);
        while (running.get()) {
            try {
                System.out.println("線程正在運行(" + System.currentTimeMillis() / 1000 + "): " + count.incrementAndGet());
                Thread.sleep(interval);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("線程被中斷,操作未能完成");
            }
            // 在此處執行一些操作
        }
        stopped.set(true);
    }
}

在上面示例中,我們添加了一個interrupt()方法,該方法將我們的running標志設置為false,并調用工作線程的interrupt()方法。

Thread.interrupt()在使用上時有一些限制的:

  • 權限校驗:如果當前線程不是要中斷的線程,Thread.interrupt() 方法會調用checkAccess() 方法進行權限檢查。如果沒有足夠的權限,會拋出SecurityException;
  • 無法強制終止線程:Thread.interrupt()方法不能強制終止線程。它只是設置中斷狀態,線程如何響應中斷完全取決于線程自身的實現。如果線程忽略了中斷狀態,線程將繼續運行。
  • I/O 操作的中斷:對于阻塞在 I/O 操作上的線程,中斷操作會關閉 I/O 通道并拋出ClosedByInterruptException。這可能導致資源泄漏或未完成的操作,因此需要謹慎處理。

如果在調用此方法時線程正在睡眠,sleep()方法將拋出InterruptedException異常退出,其他任何阻塞調用也會如此。這樣能夠快速打斷休眠和暫停。

在這個快速教程中,我們研究了如何使用原子變量,并可選擇結合調用interrupt()方法,來干凈地關閉一個線程。這絕對比調用已棄用的stop()方法要好,因為調用stop()方法可能會導致永遠鎖定和內存損壞的風險。

引申一下

雖然本文主題是終止線程,但其實可以推廣到所有while(true)的場景中。在可能出現死循環或者有條件的大循環中,我們都應該適當的增加標記位,可以快速終止循環。

比如,批量刷數據場景,通常是在循環中分頁查詢數據,然后批量處理這部分數據,處理后進入下一個批次。但是如果分頁較深,或者額運行時間較長,亦或是有bug,需要快速停止,都可以通過狀態位實現。

責任編輯:武曉燕 來源: 看山的小屋
相關推薦

2020-08-03 08:01:50

爬蟲技巧

2021-04-30 07:33:35

效率提升技巧

2021-04-28 07:22:13

HiveJson數組

2020-08-31 06:54:37

注解脫敏ELK

2020-04-20 10:47:57

Redis數據開發

2021-06-28 14:13:34

OOM內存事故

2021-08-04 07:47:18

IDEJTAGSWD

2021-06-26 09:26:01

Jupyter主題目錄

2020-04-19 21:41:13

Python數據可視化

2021-03-29 08:24:18

KubeadmKubernetes1運維

2010-07-14 10:30:26

Perl多線程

2021-11-01 13:55:38

架構

2010-02-02 14:32:32

Python線程編程

2019-03-21 09:45:11

TypeScript編程語言Javascript

2021-04-07 08:13:28

LirbeNMS開源SNMP

2023-11-01 10:49:50

Python面向對象

2025-01-16 08:38:34

2023-07-31 08:18:50

Docker參數容器

2023-09-26 12:22:37

隊列Python

2011-03-03 10:26:04

Pureftpd
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲成av| 日日操操操| 日本a∨精品中文字幕在线 亚洲91视频 | 成人在线国产 | 中文字幕日韩专区 | av电影一区二区 | 91网站在线观看视频 | 999久久久久久久久6666 | 国产乱码精品1区2区3区 | 国产精品久久久久久久久久久久午夜片 | 久久99精品久久久久久国产越南 | 中文字幕一区在线 | 欧洲高清转码区一二区 | 免费看一区二区三区 | 国产不卡一区 | 久久精品国产亚洲 | 91观看 | 亚洲精品99| 久久国产精品一区二区三区 | 亚洲一区二区三区视频 | 国产一区二区三区四区五区加勒比 | 国产美女在线免费观看 | 精品美女 | 亚洲美女网站 | 999re5这里只有精品 | 亚洲一区二区av | 日韩视频免费看 | 久久在线 | 56pao在线| 91精品久久久久久久久久小网站 | 国产精品高潮呻吟久久av野狼 | 91色啪| 999在线精品 | 国产精品久久久久久婷婷天堂 | 日本大片在线播放 | 特黄级国产片 | 国产精品亚洲一区 | 免费午夜电影 | 亚洲国产精品一区二区三区 | 久久极品 | 超碰3 |