<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    I want to fly higher
    programming Explorer
    posts - 114,comments - 263,trackbacks - 0
    1.很多人經(jīng)常會用錯interrupt方法,直接看例子
    package com.landon.mavs.example.concurrent;

    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.TimeUnit;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    /**
    *
    * interrupt容易使用出錯的例子
    *
    * <pre>
    * 1.如何結(jié)束BadRunnable這樣的任務(wù).即沒有任務(wù)結(jié)束條件來保證可以正常關(guān)閉它.使用interrupt沒有作用,其不會中斷正在運(yùn)行的線程
    * 2.結(jié)論:任務(wù)最好不要這樣寫,否則無法正常安全的關(guān)閉線程.通常需要在while()中指定任務(wù)結(jié)束條件如設(shè)置volatile變量或者判斷當(dāng)前線程是否已中斷等或者通過投遞結(jié)束消息方式(消息隊(duì)列)等
    * </pre>
    *
    * <p>
    * <a href=
    * "http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html"
    * >為何Thread#stop/resume/suspend被棄用</a>
    * <p>
    *
    * @author landon
    *
    */

    public class InterruptePuzzleExample {
       
    private static final Logger LOGGER = LoggerFactory
                .getLogger(InterruptePuzzleExample.class);

       
    public static void main(String[] args) throws Throwable {

           
    // Thread thread = new Thread(new BadRunnable());

           
    // thread.start();
           
    // 執(zhí)行interrupt,試圖終止無限循環(huán)的任務(wù)-徒勞
           
    // thread.interrupt();

            VolatileRunnable volatileTask = new VolatileRunnable();
            Thread volatileThread = new Thread(volatileTask);
            volatileThread.start();

           
    // 主線程暫停5s
            Thread.sleep(5 * 1000);
           
    // 停止任務(wù),結(jié)束volatileThread,在主線程置stopFlag(所以用volatile)
            volatileTask.stop();

            LOGGER.debug("VolatileRunnable end.");

            Thread thread2 = new Thread(new InterruptedRunnbale());
            thread2.start();

           
    // 主線程暫停1秒
            Thread.sleep(1 * 1000);
           
    // 調(diào)用interrupte結(jié)束任務(wù)->直接中斷處于sleep的任務(wù)
            thread2.interrupt();

            LOGGER.debug("main_thread2 isInterrupted:" + thread2.isInterrupted());

            QueueThread qt = new QueueThread();
            qt.start();

           
    for (int i = 1; i < 5; i++) {
                qt.offerMessage(new QueueMessage(i));
            }


           
    // 準(zhǔn)備停止qt
            qt.prepareDispose();

        }


       
    private static class BadRunnable implements Runnable {

            @Override
           
    public void run() {
                LOGGER.debug("BadRunnable begin.");

               
    // 無限循環(huán)
                while (true) {
                }

            }


        }


       
    private static class VolatileRunnable implements Runnable {
           
    // 指定volatile(更新即可視) 停止標(biāo)識
            private volatile boolean stopFlag;

           
    public void stop() {
                stopFlag = true;
            }


            @Override
           
    public void run() {
                LOGGER.debug("VolatileRunnable begin.");

               
    while (!stopFlag) {
                }

            }

        }


       
    private static class InterruptedRunnbale implements Runnable {

            @Override
           
    public void run() {
                LOGGER.debug("InterruptedRunnbale begin.");

               
    // 這里判斷調(diào)用當(dāng)前是否已被打斷做判斷
                while (!Thread.currentThread().isInterrupted()) {
                   
    try {
                       
    // 用sleep替代業(yè)務(wù)邏輯的耗時,可被打斷
                        TimeUnit.SECONDS.sleep(3);
                    }
    catch (InterruptedException e) {
                        LOGGER.debug("InterruptedRunnbale is interrupted.");

                       
    // 參考Interrupt
                       
    // API.類似調(diào)用如wait/join/sleep等方法時會收到InterruptedException且中斷狀態(tài)被清除
                        LOGGER.debug("after catch InterruptedException,thread2 isInterrupted:"
                               
    + Thread.currentThread().isInterrupted());
                       
    // 因?yàn)橹袛酄顟B(tài)被清除了.所以這次要再次調(diào)用interrupt.設(shè)置中斷狀態(tài),然后任務(wù)從循環(huán)跳出.線程結(jié)束
                        Thread.currentThread().interrupt();
                        LOGGER.debug("after again execute interrupt,thread2 isInterrupted:"
                               
    + Thread.currentThread().isInterrupted());
                    }

                }

            }

        }


       
    private static class QueueThread extends Thread {
           
    // 阻塞消息隊(duì)列
            private LinkedBlockingQueue<QueueMessage> queue = new LinkedBlockingQueue<InterruptePuzzleExample.QueueMessage>();
           
    // 因?yàn)檫@里通過投遞內(nèi)部消息方式,即在內(nèi)部單線程執(zhí)行.所以不用volatile
            private boolean stopFlag;

            @Override
           
    public void run() {
                LOGGER.debug("QueueThread begin.");

               
    while (!stopFlag) {
                   
    try {
                        QueueMessage msg = queue.take();

                       
    if (msg != null) {
                            LOGGER.debug("QueueThread process msg:" + msg);

                           
    // -1表示停止消息(注:因?yàn)槭荙ueueMessage內(nèi)部使用,可以直接訪問private屬性)
                            if (msg.msgType == -1) {
                                dispose();
                            }

                        }


                    }
    catch (InterruptedException e) {
                        LOGGER.debug("QueueMessage is interrupted.take is notify.");
                    }

                }

            }


           
    public void offerMessage(QueueMessage msg) {
                queue.offer(msg);
            }


           
    public void dispose() {
                stopFlag = true;
               
    // 這里interrupt可省略,因?yàn)榧热粓?zhí)行到了dispose,則此時一定未阻塞
               
    // interrupt();
            }


           
    // 準(zhǔn)備銷毀,由外部線程進(jìn)行調(diào)用
            public void prepareDispose() {
                LOGGER.debug("QueueThread prepare dispose.");
                offerMessage(new QueueMessage(-1));
            }

        }


       
    private static class QueueMessage {
           
    // 消息類型
            private int msgType;

           
    public QueueMessage(int type) {
                msgType = type;
            }


            @Override
           
    public String toString() {
               
    return "QueueMessage [msgType=" + msgType + "]";
            }


        }

    }



    2.很多人經(jīng)常分不清interrupted和isInterrupted兩個方法的區(qū)別,看例子
    package com.landon.mavs.example.concurrent;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    /**
    *
    * 使用Thread#interrupted/Thread#isInterrupted
    *
    * <pre>
    * 1.個人認(rèn)為interrupted方法是返回之前的中斷狀態(tài)并清除中斷狀態(tài) 2.而isInterrupted只是返回線程的中斷狀態(tài)而已
    * 3.而對于interrupt方法
    * ,對于諸如可拋出InterruptedException的一些方法,線程收到InterruptedException后會清除中斷狀態(tài)
    * ;反之則會設(shè)置狀態(tài)中斷{仔細(xì)參考Thread#interrupt的api doc}{@link InterruptThread3}}
       *【landon認(rèn)為因阻塞的線程被interrupt后,雖然是收到了異常,但是卻中斷了阻塞,其實(shí)是可以繼續(xù)運(yùn)行的!所以會清除中斷狀態(tài)】
    * </pre>
      * <pre>
      *  if (Thread.interrupted())  // Clears interrupted status!
      *      throw new InterruptedException();
      * </pre>
    *
    * <pre>
    * public boolean isInterrupted() {
    *     return isInterrupted(false);
    * }
    *
    * 靜態(tài)方法->針對當(dāng)前調(diào)用線程
    * public static boolean interrupted() {
    *     return currentThread().isInterrupted(true);
    * }
    *
    * private native boolean isInterrupted(boolean ClearInterrupted);
    * </pre>
    *
    * @author landon
    *
    */

    public class ThreadInterruptedExample {
       
    private static final Logger LOGGER = LoggerFactory
                .getLogger(ThreadInterruptedExample.class);

       
    public static void main(String[] args) throws Exception {
            InterruptThread it = new InterruptThread();
            it.start();

            InterruptThread2 it2 = new InterruptThread2();
            it2.start();

            InterruptThread3 it3 = new InterruptThread3();
           
    // 此時it3阻塞在wait方法內(nèi)
            it3.start();
           
    // 在外部調(diào)用iterrupt->it3收到InterruptedException->中斷狀態(tài)清除
            it3.interrupt();

           
    // true,因?yàn)檫@個是主線程調(diào)用的.所以此時it3還未被清除中斷狀態(tài)
            LOGGER.debug("it3.isInterrupted:" + it3.isInterrupted());
           
    // 做了一個等待.
            Thread.sleep(3 * 1000);
           
    // false,此時it3的中斷狀態(tài)已經(jīng)被清楚
            LOGGER.debug("it3.isInterrupted:" + it3.isInterrupted());
        }


       
    private static class InterruptThread extends Thread {
            @Override
           
    public void run() {
               
    // false
                LOGGER.debug("InterruptThread before interrupt.#interrupted:"
                       
    + interrupted());
               
    // false
                LOGGER.debug("InterruptThread before interrupt.#isInterrupted:"
                       
    + isInterrupted());

               
    // 調(diào)用interrupt,這里直接設(shè)置了中斷狀態(tài)
                LOGGER.debug("InterruptThread execute interrupt.");
                interrupt();

               
    // true
               
    // 調(diào)用了#interrupt->#interrupted返回true->由下面的輸出可以看到,其清除了中斷狀態(tài),所以下面的#isInterrupted返回了false
                LOGGER.debug("InterruptThread after interrupt.#interrupted:"
                       
    + interrupted());
               
    // false
                LOGGER.debug("InterruptThread after interrupt.#isInterrupted:"
                       
    + isInterrupted());
            }

        }


       
    private static class InterruptThread2 extends Thread {
            @Override
           
    public void run() {
               
    // false
                LOGGER.debug("InterruptThread2 before interrupt.#interrupted:"
                       
    + interrupted());
               
    // false
                LOGGER.debug("InterruptThread2 before interrupt.#isInterrupted:"
                       
    + isInterrupted());

               
    // 調(diào)用interrupt
                LOGGER.debug("InterruptThread2 execute interrupt.");
                interrupt();

               
    // true 這里#interrupt#->isInterrupted->返回true,即該方法不影響線程的中斷狀態(tài)
                LOGGER.debug("InterruptThread2 after interrupt.#isInterrupted:"
                       
    + isInterrupted());

               
    // true 這里#interrupted依然返回true并清除了中斷狀態(tài).所以下面的輸出返回false
                LOGGER.debug("InterruptThread2 after interrupt.#interrupted:"
                       
    + interrupted());

               
    // false
                LOGGER.debug("InterruptThread2.#isInterrupted:" + isInterrupted());

               
    // false 這里再次調(diào)用#interrupted->返回了false.因?yàn)榇藭r的狀態(tài)狀態(tài)已經(jīng)為false了
                LOGGER.debug("InterruptThread2.#interrupted:" + interrupted());

            }

        }


       
    private static class InterruptThread3 extends Thread {
           
    private final Object lock = new Object();

            @Override
           
    public void run() {
               
    synchronized (lock) {
                   
    try {
                        lock.wait();
                    }
    catch (InterruptedException e) {
                        LOGGER.debug(
    "InterruptThread3#wait,is interrupted..");
                       
    // false
                        LOGGER.debug("InterruptThread3#wati,receive InterruptedException.#isInterrupted:"
                               
    + isInterrupted());
                    }

                }

            }

        }

    }



    3.總結(jié):通過代碼的方式簡單的總結(jié)了線程的interrupt,interrupted,isInterrupted三個方法.另外還提供了幾個正確結(jié)束線程的簡單方法demo.
    posted on 2013-12-06 17:11 landon 閱讀(2041) 評論(0)  編輯  收藏 所屬分類: Program
    主站蜘蛛池模板: 成人毛片免费视频| 国产精品内射视频免费| 99久久国产免费中文无字幕| 国产亚洲蜜芽精品久久| 欧美日韩亚洲精品| 精品久久久久久久免费加勒比| 精品丝袜国产自在线拍亚洲| 日本人的色道免费网站| 在线综合亚洲中文精品| 国产美女无遮挡免费视频网站 | 67194熟妇在线永久免费观看| 天堂在线免费观看中文版| 亚洲国产成人久久一区WWW| 黄色网址在线免费观看| 四虎永久在线精品免费观看视频 | 亚洲成av人片在线观看无码不卡| 亚洲成人一级电影| 美女视频黄a视频全免费| 亚洲女女女同性video| 99久久久国产精品免费牛牛 | 亚洲Av熟妇高潮30p| 无套内谢孕妇毛片免费看看| 亚洲国产精品综合久久网络| 国产日韩精品无码区免费专区国产| 亚洲中文字幕日产乱码高清app| 亚洲Av永久无码精品黑人| 亚洲精品NV久久久久久久久久| 美女无遮挡拍拍拍免费视频| 久久精品国产亚洲AV无码娇色| aa级一级天堂片免费观看| 边摸边吃奶边做爽免费视频99| 国产亚洲一区二区精品| 中文字幕无线码中文字幕免费| 亚洲影院在线观看| 国产成人精品男人免费| 成人无码WWW免费视频| 伊人久久大香线蕉亚洲| 国产v精品成人免费视频400条| 男男gay做爽爽的视频免费| 久久久久亚洲Av片无码v| 四虎影院免费视频|