<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)常會(huì)用錯(cuò)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容易使用出錯(cuò)的例子
    *
    * <pre>
    * 1.如何結(jié)束B(niǎo)adRunnable這樣的任務(wù).即沒(méi)有任務(wù)結(jié)束條件來(lái)保證可以正常關(guān)閉它.使用interrupt沒(méi)有作用,其不會(huì)中斷正在運(yùn)行的線程
    * 2.結(jié)論:任務(wù)最好不要這樣寫(xiě),否則無(wú)法正常安全的關(guān)閉線程.通常需要在while()中指定任務(wù)結(jié)束條件如設(shè)置volatile變量或者判斷當(dāng)前線程是否已中斷等或者通過(guò)投遞結(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,試圖終止無(wú)限循環(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.");

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

            }


        }


       
    private static class VolatileRunnable implements Runnable {
           
    // 指定volatile(更新即可視) 停止標(biāo)識(shí)
            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ù)邏輯的耗時(shí),可被打斷
                        TimeUnit.SECONDS.sleep(3);
                    }
    catch (InterruptedException e) {
                        LOGGER.debug("InterruptedRunnbale is interrupted.");

                       
    // 參考Interrupt
                       
    // API.類(lèi)似調(diào)用如wait/join/sleep等方法時(shí)會(huì)收到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)檫@里通過(guò)投遞內(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)部使用,可以直接訪問(wèn)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,則此時(shí)一定未阻塞
               
    // interrupt();
            }


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

        }


       
    private static class QueueMessage {
           
    // 消息類(lèi)型
            private int msgType;

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


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


        }

    }



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

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

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

           
    // true,因?yàn)檫@個(gè)是主線程調(diào)用的.所以此時(shí)it3還未被清除中斷狀態(tài)
            LOGGER.debug("it3.isInterrupted:" + it3.isInterrupted());
           
    // 做了一個(gè)等待.
            Thread.sleep(3 * 1000);
           
    // false,此時(shí)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(shí)的狀態(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é):通過(guò)代碼的方式簡(jiǎn)單的總結(jié)了線程的interrupt,interrupted,isInterrupted三個(gè)方法.另外還提供了幾個(gè)正確結(jié)束線程的簡(jiǎn)單方法demo.
    posted on 2013-12-06 17:11 landon 閱讀(2041) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Program
    主站蜘蛛池模板: 亚洲精品无码永久中文字幕| 亚洲娇小性xxxx| 综合在线免费视频| 亚洲精品人成网线在线播放va| 国产精品久免费的黄网站| 中文字幕免费在线视频| 亚洲成aⅴ人片在线影院八| 国产91在线免费| 99ee6热久久免费精品6| 粉色视频成年免费人15次| 久久久亚洲精品国产| 国产无遮挡吃胸膜奶免费看| 一级特黄录像免费播放肥| 亚洲国产成人在线视频| 丝袜熟女国偷自产中文字幕亚洲| 999久久久免费精品国产| 国产免费一区二区三区免费视频| 亚洲综合校园春色| 久久久青草青青亚洲国产免观| 日韩精品免费一区二区三区| 免费人成在线观看视频高潮| 久久精品国产亚洲av天美18| 精品亚洲国产成AV人片传媒| 亚洲综合亚洲综合网成人| 女性自慰aⅴ片高清免费| 日本免费人成网ww555在线| 猫咪免费人成网站在线观看入口 | 嫩草影院在线播放www免费观看| 亚洲色偷偷色噜噜狠狠99网| 久久精品九九亚洲精品| 久久亚洲av无码精品浪潮| 好男人看视频免费2019中文| 日韩精品无码免费一区二区三区 | 亚洲午夜福利在线观看| 国产精品四虎在线观看免费| 99久久99久久精品免费看蜜桃 | 色窝窝亚洲AV网在线观看| 亚洲AV无码国产精品色| 亚洲AV乱码一区二区三区林ゆな| 亚洲AV无码乱码在线观看性色扶| 午夜时刻免费入口|