Java併發 基礎 二

1 、線程中斷:

線程中斷是一種重要的線程協作機制。線程中斷並不會讓線程退出,只是給線程發送一個通知,線程執行過程會檢測到這個通知,然後可以自定義做出動作,比如退出,但也並不是都是退出。

線程中有三個有關中斷的方法:

public void  interrupt()  中斷線程
public booklean  isInterrupted() 判斷是否被中斷,不清除當前中斷狀態
public static  boolean interrupt() 判斷是否被中斷,並清除當前中斷狀態。
public class ThreadInterrupt {

    public static void main(String args[]) throws InterruptedException {
        Thread t1 = new Thread() {
            public void run() {

                while (true) {

                    if(Thread.currentThread().isInterrupted()){ //1 在中斷處理中並未執行退出
                                                                // 2 此方法並未清除中斷標誌位,因此還會被檢測到
                        System.out.println("線程第一次檢測到中斷,並不退出");

                    }
                    System.out.println("線程執行過程中 ");

                    if(Thread.currentThread().isInterrupted()){
                        System.out.println("線程再次檢測到中斷,然後退出");
                        break;
                    }

                    System.out.println("線程執行過程中 ");
                    Thread.yield();
                }

            }

        };

        t1.start();
        Thread.sleep(3000);
        t1.interrupt();

    }
}

Thead.sleep() 方法會讓當前線程休眠若干時間,會拋出一個InterruptedException 中斷異常。 不是運行時異常,程序必須捕獲它。,當線程在sleep休眠時,如果被中斷,這個異常就會產生。

Thread.sleep 方法由於中斷而拋出異常,此時,它會清除中斷標記,如果不加處理,那麼在下一次循環開始時,就無法捕獲這個中斷,故在異常處理中,再次設置中斷標記位。

2、等待 wait通知 notify

爲了支持多線程之間的協作,jdk提供了兩個非常重要的接口:wait 和notify方法。這兩個方法在Object類中定義,這意味着任何對象都可以調用這兩個方法,但是 wait和notify不是隨意調用的,它必須包含在對應的synchronized語句中。還有個地方需要注意,儘量不在Thread實例上調用wait和notify方法。無論是wait還是notify,都需要首先獲得目標對象的一個監視器。

線程執行wait和notify的流程:

T1在執行object.wait方法之前首先獲得object對象的監視器,執行之後,釋放object的監視器,此時線程就會進入等待狀態, 等待其他線程的喚醒。

T2 在notify調用前,也必須獲得object的監視器,此時T1已經釋放了這個監視器,因此T2可以順利獲得object的監視器。接着T2執行了notify方法嘗試喚醒一個等待線程,這裏是隨機喚醒,假設喚醒了T1 。T1被喚醒後,要做的第一件事並不是執行後續的代碼,而是嘗試從新獲得object的監視器,而這個監視器也正是t1在wait方法執行前所持有的那個。

object.wait 和thread.sleep 方法都可以讓線程等待若干時間。除了wait可以被喚醒外,另外一個主要的區別就是wait 方法會釋放目標對象的鎖,而Thread.sleep方法不會釋放任何資源。

3、掛起 suspend 繼續執行 resume

在導致線程暫停的同時,並不會釋放任何資源。此時其他任何線程想要訪問被它暫用的鎖時,都會被牽連。導致無法正常繼續運行。直到resume操作,假設無resume的執行,或者resume已經提前調用過了,那麼這個線程永遠處於掛起狀態了。

4、等待線程結束 join 謙讓 yield

join有兩個方法簽名,無參數的join,表示無限期等待, 有參數join表示等待指定的時間。

在線程T1中調用 T2.join 表示等待T2線程調用完畢之後,纔會調用繼續調用線程T1。
(顯然在本身的方法裏,調用自身的join方法是沒有意義的。)

yield 總是一個靜態方法,一旦執行,它會使當前線程讓出CPU,但要注意,讓出CPU並不是表示當前線程不執行了。當前線程在讓出CPU後,還會進行CPU資源的爭奪。

5、守護線程

Daemon 是一種特殊的線程,它是系統的守護者,在後臺默默地完成一些系統性的服務。 比如垃圾回收線程,JIT線程。 當一個Java應用內,只有守護線程時,Java虛擬機就會自然退出。

6、關於synchronized的用法:

指定加鎖對象: 對給定對象加鎖,進入同步代碼前要獲得給定對象的鎖。
直接作用於實例方法: 相當於對當前實例加鎖,進入同步代碼前要獲得當前實例的鎖。
直接作用於靜態方法:相當於對當前類加鎖,進入同步代碼前要獲得當前類的鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章