java取消線程實(shí)例

本文展示一個(gè)常見的取消線程的方法。

錯(cuò)誤實(shí)例

class BrokenPrimeProducer extends Thread {
    private final BlockingQueue<BigInteger> queue;
    private volatile boolean cancelled = false;

    BrokenPrimeProducer(BlockingQueue<BigInteger> queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            BigInteger p = BigInteger.ONE;
            while (!cancelled){
                queue.put(p = p.nextProbablePrime());
            }    
        } catch (InterruptedException consumed) {
        }
    }

    public void cancel() {
        cancelled = true;
    }
}

這里試圖用一個(gè)標(biāo)志來跳出while循環(huán),理論上貌似可行,但是這里使用的是阻塞的操作,那么就出現(xiàn)一種場景,線程永遠(yuǎn)阻塞在put方法,根本就沒來得及下個(gè)循環(huán)去判斷cancelled這個(gè)條件,造成永遠(yuǎn)無法停止掉線程。

正確方法

通過中斷來取消線程。

public class PrimeProducer extends Thread {
    private final BlockingQueue<BigInteger> queue;

    PrimeProducer(BlockingQueue<BigInteger> queue) {
        this.queue = queue;
    }

    public void run() {
        try {
            BigInteger p = BigInteger.ONE;
            while (!Thread.currentThread().isInterrupted()){
                queue.put(p = p.nextProbablePrime());
            }    
        } catch (InterruptedException consumed) {
            /* Allow thread to exit */
        }
    }

    public void cancel() {
        interrupt();
    }
}

這里的關(guān)鍵是queue的put操作能夠響應(yīng)interrupt方法,拋出InterruptedException,倒不是因?yàn)閣hile條件里頭的isInterrupted,這里while條件換成boolean可以照樣可以。

小結(jié)

調(diào)用interrupt并不意味著立即停止目標(biāo)線程正在進(jìn)行的工作,而只是傳遞了請求中斷的消息。對中斷操作的正確理解是:它并不會真正地中斷一個(gè)正在運(yùn)行的線程,而只是發(fā)出中斷請求,然后由線程在下一個(gè)合適的時(shí)刻中斷自己。

有些方法,例如wait、sleep和join等,將嚴(yán)格地處理這種請求,當(dāng)它們收到中斷請求或者在開始執(zhí)行時(shí)發(fā)現(xiàn)某個(gè)已被設(shè)置好的中斷狀態(tài)時(shí),將拋出一個(gè)異常。設(shè)計(jì)良好的方法可以完全忽略這種請求,只要它們能使調(diào)用代碼對中斷請求進(jìn)行某種處理。

設(shè)計(jì)糟糕的方法可能會屏蔽中斷請求,從而導(dǎo)致調(diào)用棧中的其他代碼無法對中斷請求作出響應(yīng)。在使用靜態(tài)的interrupted時(shí)應(yīng)該小心,因?yàn)樗鼤宄?dāng)前線程的中斷狀態(tài)。如果在調(diào)用interrupted時(shí)返回了true,那么除非你想屏蔽這個(gè)中斷,否則必須對它進(jìn)行處理—可以拋出InterruptedException,或者通過再次調(diào)用interrupt來恢復(fù)中斷狀態(tài)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容