Java之正確的停止線程

API提供的方法存在的問題

public class StopThread3 {
    private static Object lock = new Object();
    private static int number = 0;
    static int tmp = 0;
    public static void main(String[] args) {
        ThreadOne t1 = new ThreadOne();
        t1.start();
        ThreadTwo t2 = new ThreadTwo();
        t2.start();
        t1.stop();
        t2.stop();
    }

    static class ThreadOne extends Thread {

        public void run() {
            add();
        }
        private void add() {

            while (true) {
                synchronized (lock) {
                    System.out.println("number=" + number);
                    tmp++;
                    number++;
                }
            }
        }
    }

    static class ThreadTwo extends Thread {

        public void run() {
            add();
        }
        private void add() {
            while (true) {
                synchronized (lock) {
                    System.out.println("number=" + number);
                    tmp++;
                    number++;
                }
            }
        }

    }

}

其中的一次輸出:
number=347
number=348
number=348
number=349
number=350

替代stop的方法

class MyThread extends Thread {
     volatile boolean flag = false;
     public void stopThread(){
         flag = true;
     }
     @Override
     public void run() {
         while (flag) {                
             process();
         }
     }
     private void process() {
         ...
     }
 }

volatile

flag必須使用volatile修飾侈净,或者訪問flag的方法是同步的尊勿,如下:

class MyThread extends Thread {
    boolean flag = false;  
    public synchronized void stopThread(){
        flag = true;
    }
    @Override
    public void run() {  
        while (flag) {                
            process();
        }

    }
    private void process() {
        ...
    }
}

這個是很常用的方法但是在某些情況下并不適用。
在上面的荔枝中如果process()是一個很耗時的操作畜侦,當在別的線程中修改了flag并不能停止線程。這時需要用到Thread.interrupt躯保。

使用 Thread.interrupt

class MyThread extends Thread {
        public void stopThread() {
            interrupt();
        }
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                process();
            }
            System.out.println("...end...");
        }
        private void process() {
            System.out.println("---process---");
            try {
                Thread.sleep(1000 * 1000);
            } catch (InterruptedException ex) {
                System.out.println("InterruptedException");
            }
        }
  }

Thread.interrupt只能中斷響應(yīng)InterruptedException的線程旋膳。如果將上例中的process()改為下面的形式,將不能終止線程的執(zhí)行途事。

private void process() {
  System.out.println("---process---");
  while (true) {}
}

Override interrupt()

對于不能響應(yīng)InterruptedException的情況可以針對具體的情況验懊,重寫interrupt()方法。如果我們試圖讀取一個已經(jīng)關(guān)閉的InputStream時尸变,會產(chǎn)生一個stream is closed的錯誤义图,當我們在interrupt方法中關(guān)閉了InputStream,讀取這個InputStream的線程就會中斷。記渍倮谩:使用此方法不能在catch進行可以中終止線程的操作,如printStackTrace()碱工。

public class StopThread2 {

    public static void main(String[] args) {
        new StopThread2().test();
    }

    private void test() {
        final MyThread myThread = new MyThread();
        myThread.start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1200);
                } catch (InterruptedException ex) {
                }
                myThread.stopThread();

            }
        }).start();

    }

    class MyThread extends Thread {

        private URLConnection conn;
        private volatile InputStream in;

        public void stopThread() {
            interrupt();
        }

        @Override
        public void interrupt() {
            try {
                in.close();
            } catch (IOException ex) {
                System.out.println("IOException:" + ex.getMessage());
            }
            super.interrupt();
        }

        @Override
        public void run() {
            try {
                URL url = new URL("http://new.hellopojo.site/AndroidDev");

                conn = url.openConnection();
                in = conn.getInputStream();

                process(in);

                System.out.println("...end...");
            } catch (Exception ex) {
                System.out.println("---" + ex.getStackTrace());
            }
        }

        private void process(InputStream in) {
            try {
                System.out.println("---process---");
                InputStreamReader isr = new InputStreamReader(in, "utf-8");
                BufferedReader reader = new BufferedReader(isr);
                String line = null;
                while ((line = reader.readLine()) != null) {
                    System.out.println("" + line);
                }
            } catch (IOException ex) {
                System.out.println("IOException:" + ex.getMessage());
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市奏夫,隨后出現(xiàn)的幾起案子怕篷,更是在濱河造成了極大的恐慌,老刑警劉巖酗昼,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廊谓,死亡現(xiàn)場離奇詭異,居然都是意外死亡麻削,警方通過查閱死者的電腦和手機蒸痹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呛哟,“玉大人叠荠,你說我怎么就攤上這事∈玻” “怎么了蝙叛?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長公给。 經(jīng)常有香客問我借帘,道長,這世上最難降的妖魔是什么淌铐? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任肺然,我火速辦了婚禮,結(jié)果婚禮上腿准,老公的妹妹穿的比我還像新娘际起。我一直安慰自己拾碌,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布街望。 她就那樣靜靜地躺著校翔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪灾前。 梳的紋絲不亂的頭發(fā)上防症,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音哎甲,去河邊找鬼蔫敲。 笑死,一個胖子當著我的面吹牛炭玫,可吹牛的內(nèi)容都是我干的奈嘿。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼吞加,長吁一口氣:“原來是場噩夢啊……” “哼裙犹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起榴鼎,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤伯诬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后巫财,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盗似,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年平项,在試婚紗的時候發(fā)現(xiàn)自己被綠了赫舒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡闽瓢,死狀恐怖接癌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扣讼,我是刑警寧澤缺猛,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站椭符,受9級特大地震影響荔燎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜销钝,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一有咨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蒸健,春花似錦座享、人聲如沸婉商。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丈秩。三九已至,卻和暖如春淳衙,著一層夾襖步出監(jiān)牢的瞬間癣籽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工滤祖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓶籽。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓匠童,卻偏偏與公主長得像,于是被迫代替她去往敵國和親塑顺。 傳聞我的和親對象是個殘疾皇子汤求,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容