日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

對于很多剛接觸編程的人來說,對于線程中斷和線程阻塞兩個概念,經常性是混淆起來用,單純地認為線程中斷與線程阻塞的概念是一致的,都是值線程運行狀態的停止。其實這個觀點是錯誤的,兩者之前有很大的區別,下文就著重介紹兩者之間的區別。

線程中斷

在一個線程正常結束之前,如果被強制終止,那么就有可能造成一些比較嚴重的后果,設想一下如果現在有一個線程持有同步鎖,然后在沒有釋放鎖資源的情況下被強制休眠,那么這就造成了其他線程無法訪問同步代碼塊。因此我們可以看到在 JAVA 中類似 Thread#stop() 方法被標為 @Deprecated。

針對上述情況,我們不能直接將線程給終止掉,但有時又必須將讓線程停止運行某些代碼,那么此時我們必須有一種機制讓線程知道它該停止了。Java 為我們提供了一個比較優雅的做法,即可以通過 Thread#interrupt() 給線程該線程一個標志位,讓該線程自己決定該怎么辦。

接下來就用代碼來延時下 interrupt() 的作用:

Copypublic class InterruptDemo {

    static class MyThread implements Runnable {
        @Override
        public void run() {
            for (int i= 0; !Thread.currentThread().isInterrupted() && i < 200000; i++) {
                System.out.println(Thread.currentThread().getName() + ":i = " + i);
            }
        }
    }

    public static void mAIn(String[] args) throws InterruptedException {
        Thread myThread = new Thread(new MyThread());
        myThread.start();

        // 讓線程運行一段時間
        Thread.sleep(5);

        myThread.interrupt();

        // 等待 myThread 運行停止
        myThread.join();
        System.out.println("end");
    }

}

以上代碼的運行結果如下:

 

可以看到,當前線程并沒有按 for 循環中的結束量 20000 去跑,而是在被中斷后,停止了當前了 for 循環。所以我們可以利用 interrupt 配置線程使用,使得線程在一定的位置停止下來。

不過到這里可能會讓人產生一些疑惑,因為在這里看起來,當前線程像是被阻塞掉了,其實并不是的,我們可以利用下面這段代碼來演示下:

Copypublic class InterruptDemo {

    static class MyThread implements Runnable {
        @Override
        public void run() {
            for (int i= 0; i < 200000; i++) {
                System.out.println(Thread.currentThread().getName() + ":i = " + i);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Thread myThread = new Thread(new MyThread());
        myThread.start();

        // 讓線程運行一段時間
        Thread.sleep(5);

        myThread.interrupt();

        // 等待 myThread 運行停止
        myThread.join();
        System.out.println("end");
    }

}

上面這段代碼的運行結果如下:

 

可見,線程一直打印到 20000,執行完畢后推出線程,并沒有像我們預料中在某處中斷。所以我們可以得出結論:單純用 interrupt() 中斷線程方法并不能停止當前正在運行的線程,需要配合其他方法才能正確停止線程。

了解完中斷的基本概念后,線程的中斷還有需要其他需要注意的點:

  • 設置線程中斷后,線程內調用 wait()、join()、slepp() 方法中的一種,都會拋出 InterruptedException 異常,且中斷標志位被清除,重新設置為 false;
  • 當線程被阻塞,比如調用了上述三個方法之一,那么此時調用它的 interrupt() 方法,也會產生一個 InterruptedException 異常。因為沒有占有 CPU 的線程是無法給自己設置中斷狀態位置的;
  • 嘗試獲取一個內部鎖的操作(進入一個 synchronized 塊)是不能被中斷的,但是 ReentrantLock 支持可中斷的獲取模式:tryLock(long time, TimeUnit unit);
  • 當代碼調用中需要拋出一個 InterruptedException,捕獲之后,要么繼續往上拋,要么重置中斷狀態,這是最安全的做法。

線程阻塞

上面講完了線程中斷,它其實只是一個標志位,并不能讓線程真正的停止下來,那么接下來就來介紹如何真正讓線程停止下來。

對于這個問題,Java 中提供了一個較為底層的并發工具類:LockSupport,該類中的核心方法有兩個:park(Object blocker) 以及 unpark(Thread thred),前者表示阻塞指定線程,后者表示喚醒指定的線程。

Copy// java.util.concurrent.locks.LockSupport

public static void park(Object blocker) {
    Thread t = Thread.currentThread();
    setBlocker(t, blocker);
    UNSAFE.park(false, 0L);
    setBlocker(t, null);
}

public static void unpark(Thread thread) {
    if (thread != null)
        UNSAFE.unpark(thread);
}

該方法在 Java 的語言層面上比較簡單,最終也是去調用 UNSAFE 中的 native 方法。真正涉及到底層的東西需要去理解 JVM 的源碼,這里就不做太多的介紹。不過我們可以用一個簡單的例子來演示下這兩個方法:

Copypublic class LockSupportDemo {

    static class MyThread implements Runnable {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + "開始執行");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + "執行結束");
        }
    }

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

        Thread thread = new Thread(new MyThread(), "線程:MyThread");
        thread.start();
        Thread.sleep(100);
        System.out.println(Thread.currentThread().getName() + "主線程執行中");
        LockSupport.unpark(thread);
        System.out.println(Thread.currentThread().getName() + "主線程執行結束");
    }

}

上述代碼的執行結果為:

Copy線程:MyThread開始執行
main主線程執行中
線程:MyThread執行結束
main主線程執行結束

可以看到,myThread 線程在開始執行后停止了下來,等到主線程重新調用 LockSupport.unpark(thread) 后才重新開始執行。

原文鏈接:
https://mp.weixin.qq.com/s/NzEFLh0_6mA-2uBL7VzAVA

分享到:
標簽:Java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定