1. 程式人生 > >執行緒_join yield 與interrupt執行緒

執行緒_join yield 與interrupt執行緒

join yield與中斷執行緒(2)

1、join

join()方法:加入執行緒讓呼叫的執行緒先執行指定時間或者是指向完畢

異常:InterruptedException-如果任何執行緒中斷當前執行緒。當丟擲異常時,當前執行緒的中斷狀態被清除
package com.huanghe;

/**
 * @Author: River
 * @Date:Created in  10:27 2018/5/28
 * @Description: join()方法:加入執行緒讓呼叫的執行緒先執行指定時間或者是指向完畢
 */
public class ThreadDemo2 {
    public
static void main(String[] args) { MyRunable2 mr2 = new MyRunable2(); Thread t = new Thread(mr2); t.start(); for (int i = 0; i <20 ; i++) { System.out.println(Thread.currentThread().getName()+"--"+i); try { Thread.sleep(500); } catch
(InterruptedException e) { e.printStackTrace(); } if (i == 10) { try { t.join();//讓t執行緒執行完畢 }catch (InterruptedException e){ e.printStackTrace(); } } } } } class MyRunable2 implements Runnable{ @Override
public void run() { for (int i = 0; i <20 ; i++) { System.out.println(Thread.currentThread().getName()+"--"+i); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } 執行的結果如下: main--0 Thread-0--0 main--1 Thread-0--1 main--2 Thread-0--2 main--3 Thread-0--3 Thread-0--4 main--4 Thread-0--5 main--5 Thread-0--6 main--6 Thread-0--7 main--7 main--8 Thread-0--8 Thread-0--9 main--9 main--10 Thread-0--10 Thread-0--11 Thread-0--12 Thread-0--13 Thread-0--14 Thread-0--15 Thread-0--16 Thread-0--17 Thread-0--18 Thread-0--19 main--11 main--12 main--13 main--14 main--15 main--16 main--17 main--18 main--19

2、yield()

yield:

解釋它之前,先簡述下,多執行緒的執行流程:多個執行緒併發請求執行時,由cpu決定優先執行哪一個,

即使通過thread.setPriority(),設定了執行緒的優先順序,也不一定就是每次都先執行它

yield,表示暫停當前執行緒,執行其他執行緒(包括自身執行緒) 由cpu決定

public class TestYield implements Runnable {    

        public void run() {    

                System.out.println("first: " + Thread.currentThread().getName() );    
                // 暫停當前正在執行的執行緒物件,並執行其他執行緒,就是進入就緒狀態    
                Thread.currentThread().yield();    
                // 可能還會執行 本執行緒: 以下語句不一定緊接著上面的語句被執行,可能其他執行緒的先執行了  
                System.out.println("second: " + Thread.currentThread().getName() );    

        }    

        public static void main(String[] args) {    
            TestYield runn = new TestYield();    
            Thread t1 = new Thread(runn);    
            Thread t2 = new Thread(runn);    
            Thread t3 = new Thread(runn);    

            t2.setPriority(t2.getPriority()+1); //設定t2的執行緒優先順序   
            t1.start();    
            t2.start();    
            t3.start();    

        }    
}

多次執行,看執行結果

first: Thread-0  
first: Thread-2  
second: Thread-2  
first: Thread-1  
second: Thread-0  
second: Thread-1  

其實預設情況下,多執行緒時,cpu就會切換執行的任務執行緒,而yield方法,只是人為的通知系統,進行切換,
且有一定機率能切換回本身

3、中斷

public void interrupt():
//中斷這個執行緒
//除非當前執行緒中斷自身,這是始終允許的
//可以使用interrupt()方法將執行緒從凍結狀態強制恢復到執行狀態中來,讓執行緒具備CPU的執行資格,但是強制動作會發生中斷異常InterruptedException,記得需要進行處理
public static boolean interrupted()
 //測試當前執行緒是否中斷。該方法可以清除中斷狀態。換句話說,如果這個方法被連續的呼叫兩次,那麼第二個呼叫將返回false(除非當前執行緒再次中斷,在第一個呼叫已經清除其中的中斷狀態之後,在第二個呼叫之前已經檢查過)
package com.huanghe.Demo;

/**
 * @Author: River
 * @Date:Created in  10:27 2018/5/28
 * @Description: join()方法:加入執行緒讓呼叫的執行緒先執行指定時間或者是指向完畢
 * (1):使用Interrupt方法中斷執行緒,設定一箇中斷標記
 * (2):自定義中斷標記
 */
public class ThreadDemo2 {
    public static void main(String[] args) {

        MyRunable2 mr2 = new MyRunable2();
        Thread t = new Thread(mr2);
        t.start();

        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           if (i == 10) {
               t.interrupt();//中斷執行緒,中斷標記
            }
        }
    }
}

class MyRunable2 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            if (Thread.interrupted()){//測試中斷狀態,此方法會把中斷標記清除
                break;
            }
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

執行的結果是:

Thread-0--0
main--0
main--1
Thread-0--1
Thread-0--2
main--2
Thread-0--3
main--3
Thread-0--4
main--4
Thread-0--5
main--5
Thread-0--6
main--6
Thread-0--7
main--7
Thread-0--8
main--8
Thread-0--9
main--9
Thread-0--10
main--10
Thread-0--11
main--11
Thread-0--12
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.huanghe.Demo.MyRunable2.run(ThreadDemo2.java:53)
    at java.lang.Thread.run(Thread.java:745)
main--12
Thread-0--13
main--13
Thread-0--14
main--14
Thread-0--15
main--15
Thread-0--16
main--16
Thread-0--17
main--17
Thread-0--18
main--18
Thread-0--19
main--19

為什麼會出現丟擲異常之後又繼續的執行呢?

因為sleep方法會丟擲中斷異常,InterruptedException:如果任何執行緒中斷當前執行緒,就會丟擲中斷異常;因為在sleep中會丟擲中斷異常,並且異常會被清除

package com.huanghe;

/**
 * @Author: River
 * @Date:Created in  10:27 2018/5/28
 * @Description: join()方法:加入執行緒讓呼叫的執行緒先執行指定時間或者是指向完畢
 */
public class ThreadDemo2 {
    public static void main(String[] args) {

        MyRunable2 mr2 = new MyRunable2();
        Thread t = new Thread(mr2);
        t.start();

        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           if (i == 10) {
//                try {
//                    t.join();//讓t執行緒執行完畢
//                }catch (InterruptedException e){
//                    e.printStackTrace();
//                }
               t.interrupt();//1、中斷執行緒,中斷標記
            }
        }

    }
}

class MyRunable2 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
             if (Thread.interrupted()){//4)測試中斷狀態,此方法會把中斷標記清除
                break;
            }
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace(); //2、因為在sleep中會丟擲中斷異常,並且異常會被清除
                 t.interrupt();//3、中斷標記需要再次的被打上
            }
        }
    }
}
//執行的結果
main--0
Thread-0--0
main--1
java.lang.InterruptedException: sleep interrupted
Thread-0--1
    at java.lang.Thread.sleep(Native Method)
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
java.lang.InterruptedException: sleep interrupted
main--2
Thread-0--2
    at java.lang.Thread.sleep(Native Method)
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
main--3
java.lang.InterruptedException: sleep interrupted
Thread-0--3
    at java.lang.Thread.sleep(Native Method)
Thread-0--4
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
main--4
java.lang.InterruptedException: sleep interrupted
Thread-0--5
    at java.lang.Thread.sleep(Native Method)
Thread-0--6
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
Thread-0--7
main--5
java.lang.InterruptedException: sleep interrupted
Thread-0--8
    at java.lang.Thread.sleep(Native Method)
main--6
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
Thread-0--9
    at java.lang.Thread.run(Thread.java:745)
java.lang.InterruptedException: sleep interrupted
main--7
    at java.lang.Thread.sleep(Native Method)
Thread-0--10
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
Thread-0--11
    at java.lang.Thread.run(Thread.java:745)
java.lang.InterruptedException: sleep interrupted
main--8
    at java.lang.Thread.sleep(Native Method)
Thread-0--12
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
java.lang.InterruptedException: sleep interrupted
Thread-0--13
    at java.lang.Thread.sleep(Native Method)
main--9
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
Thread-0--14
    at java.lang.Thread.run(Thread.java:745)
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
Thread-0--15
main--10
Thread-0--16
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
main--11
Thread-0--17
main--12
java.lang.InterruptedException: sleep interrupted
Thread-0--18
    at java.lang.Thread.sleep(Native Method)
Thread-0--19
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
main--13
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at com.huanghe.MyRunable2.run(ThreadDemo2.java:42)
    at java.lang.Thread.run(Thread.java:745)
main--14
main--15
main--16
main--17
main--18
main--19
會出現異常的原因是sleep()會丟擲中斷異常

從執行的結果中可以看出,程式並沒有停止執行,但是丟擲了異常,這個異常是Runable裡面的sleep丟擲的異常,t.interrup();只是做了一箇中斷標記,t是不是真的需要中斷進行,需要執行緒自己進行決定;

所以如果需要完成一個正常的中斷,需要上面的四步才可以順序的完成

4、自定義標記中斷執行緒

由於上面的中斷過程很麻煩,所以在做中斷執行緒的時候使用的是自定義中斷執行緒

package com.huanghe;

/**
 * @Author: River
 * @Date:Created in  10:27 2018/5/28
 * @Description: join()方法:加入執行緒讓呼叫的執行緒先執行指定時間或者是指向完畢
 * (1):使用Interrupt方法中斷執行緒,設定一箇中斷標記
 * (2):自定義中斷標記
 */
public class ThreadDemo2 {
    public static void main(String[] args) {

        MyRunable2 mr2 = new MyRunable2();
        Thread t = new Thread(mr2);
//        t.start();

        MyRunable3 mr3 = new MyRunable3();
        Thread t2 = new Thread(mr3);
        t2.start();

        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           if (i == 10) {
//                try {
//                    t.join();//讓t執行緒執行完畢
//                }catch (InterruptedException e){
//                    e.printStackTrace();
//                }
//               t.interrupt();//中斷執行緒,中斷標記
               mr3.flag=false;//自定義中斷異常
            }

        }

    }
}

class MyRunable2 implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            if (Thread.interrupted()){//測試中斷狀態,此方法會把中斷標記清除
                break;
            }
            System.out.println(Thread.currentThread().getName()+"--"+i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
                Thread.currentThread().interrupt();
            }
        }
    }
}


class MyRunable3 implements Runnable{

    public boolean flag=true;

    public MyRunable3(){
        flag = true;
    }

    @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();
            }
        }

    }
}