1. 程式人生 > 其它 >join加入執行緒和中斷執行緒

join加入執行緒和中斷執行緒

join方法存在於Thread類中,主要作用是使原本並航執行的執行緒變為序列執行,程式碼如下:

package thread;

public class Thread5 implements Runnable {//實現Runnable介面
    @Override
    public void run() {//重寫run方法

        for (int i = 0; i < 50; i++) {
            System.out.println("我是run執行緒" + i);
        }
    }

    public static void main(String[] args) {

        Thread5 t1 = new Thread5();//建立該類的例項物件
        Thread t = new Thread(t1);//建立Thread類的例項物件,並把需要同步執行的執行緒丟進去
        t.start();//啟動執行緒
        for (int i = 0; i < 50; i++) {
            System.out.println("我是主執行緒" + i);
            if (i == 20) {
                try {
                       t.join();//上面啟動執行緒的時候已經把分支執行緒丟進了Theard的例項裡面,所以這裡的T代表的就是主執行緒,程式碼含義為當i迴圈到20的時候,那麼分支執行緒加入進來先執行
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

注意:

  1. join加入執行緒也會丟擲異常,需要用try catch進行捕獲
  2. join方法無法用於run方法中,這和程式載入順序有關

中斷執行緒:

interrupt():中斷執行緒,它只是做了一箇中斷標記,是否中斷執行緒,由執行緒本身來決定!且如果程式丟擲一個interruptedException異常,當丟擲此異常的時候,當前執行緒的中斷狀態將被清除

interrrupted():測試當前執行緒是否中斷,且該方法也會把當前執行緒的中斷狀態清除,如果這個方法被連續呼叫兩次,那麼第二次呼叫會返回false。

public class Thread6 implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 50; i++) {//執行緒體
            if (Thread.interrupted()){//第二步,寫一個if語句判斷該執行緒是否處於中斷狀態
                break;//如果返回結果是true就退出迴圈
            }
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {//sleep方法丟擲的異常會使執行緒清除中斷狀態
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
                Thread.currentThread().interrupt();//第三步在catch處理異常的時候加入interrupt可以中斷執行緒
            }
        }
    }

    public static void main(String[] args) {
        Thread6 t1 = new Thread6();
        Thread t = new Thread(t1);
        t.start();
        for (int i = 0; i <50 ; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(i==20){
                t.interrupt();//第一步,當i=20的時候就向執行緒T傳送一箇中斷標記
            }
        }

    }
}

程式執行過程:

類載入完畢,開始尋找Main方法,找到main方法後程序繼續執行

  1. 新建一個該類的例項物件,新建一個Thread類的例項物件,並把類的例項物件丟進Thread類的例項
  2. Thread類呼叫自身的start方法啟動多執行緒,start裡面會把重寫的run方法也加入同步執行
  3. 兩個執行緒開始同步執行迴圈,進入到sleep方法中開始交替休眠執行,當main執行緒進入if語句,i=20時,會給t執行緒傳送一箇中斷標記,要求t執行緒中斷執行,t執行緒進入自身的for迴圈裡面重複執行,當接收到中斷標記時,它會進入if語句退出迴圈,迴圈結束那麼t執行緒也就結束了

自定義標記中斷執行緒:

以上中斷執行緒的方式過於麻煩,我們也可以自己定義一個標記來中斷執行緒,思路如下:

  1. 在類裡定義一個布林型別的資料型別,初始值為true
  2. 在類裡面重寫構造方法flag為true
  3. 在main方法設定執行緒終止時機,如果迴圈到20次的時候,就把flag的值置為false,程式執行到這個時候因為它的值是false了,所以執行緒會終止進行
public class Thread7 implements Runnable{
    public boolean flag = true;
    public Thread7(){
        flag = true;
    }
    public static void main(String[] args) {
        Thread7 thread7 = new Thread7();
        Thread t1 = new Thread(thread7);
        t1.start();
        for (int i = 0; i < 50; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);

            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (i==20){
                thread7.flag = false;
            }
        }
    }
    @Override
    public void run() {

        int i = 0;
        while (flag){
            System.out.println(Thread.currentThread().getName()+i++);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}