多線程學習(四)

在Java中有三種方法用於中止線程:java

    1 . 使用退出標識,使線程正常退出, 也就是當run()方法完成後終止線程.ide

    2 . 使用stop()方法強制中止線程, 可是不推薦這種方法, 由於stop和suspend , resume方法同樣, 都是做廢過時的方法, 使用這相似的方法可能致使不可預期的錯誤.測試

    3 . 使用interrupt方法終止線程.this

 

一 . interrupt()spa

    下述代碼將使用interrupt()方法進行中止線程,可是interrupt()方法的使用效果並不像for循環中的break同樣,立刻就中止循環. 調用interrupt()方法僅僅是在當前線程中打了一箇中止的標記,並非真正的中止線程.因此在使用interrupt()方法的時候還須要加入一個判斷才能夠完成線程的中止.線程

    

    代碼段:對象

public class MyThread extends Thread {
    
        @Override
        public void run() {
            super.run();
            for (int i = 0; i < 500000; i++) {
                System.out.println("i = " + (i + 1));
            }
        }
    
    }

    運行類:get

public class Test {
        public static void main(String[] args) {
            try{
                MyThread myThread = new MyThread();
                Thread thread = new Thread(myThread);
                thread.start();
                Thread.sleep(1000);
                thread.interrupt();
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    }

運行結果:同步

    

    從運行結果能夠看出,interrupt()方法並無將當前線程中止.io

二 . 判斷線程是否中止

        Java中Thread.java類中提供了兩種方法進行判斷線程是否中止的判斷

        1 . interrupted()

             測試當前線程是否已經中斷(會清除線程中斷狀態)

             測試當前線程是不是中斷狀態,執行後具備將狀態標識清除爲false的功能.

        2 . isInterrupted()

             測試線程Thread對象是否已是中斷狀態,但不提供清除狀態標識爲false的功能.

 

三 . 中止線程(異常中止)

public class MyThread extends Thread {

            @Override
            public void run() {
                super.run();
                for (int i = 0; i < 500000; i++) {
                    if (this.interrupted()) {
                        System.out.println("Thread interrupted.");
                        break;
                    }
                    System.out.println("i = " + (i + 1));
                }
                System.out.println("end.");
            }

        }
public class Test {
            public static void main(String[] args) {
                try {
                    MyThread myThread = new MyThread();
                    myThread.start();
                    myThread.setName("test");
                    Thread.sleep(1000);
                    myThread.interrupt();
                    System.out.println("線程名字 :" + myThread.getName());
                    System.out.println("線程是否中斷 : " + myThread.interrupted());
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

    運行結果:

使用這種方法將線程中止後for循環後面的代碼還會繼續運行, 若是for循環後面還存在一個或多個for循環,則該線程並不會結束.

 

因此,將第一段代碼進行修改:

public class MyThread extends Thread {

    @Override
    public void run() {
        super.run();
        try {
            for (int i = 0; i < 500000; i++) {
                if (this.interrupted()) {
                    System.out.println("Thread interrupted.");
                    throw new InterruptedException();
                }
                System.out.println("i = " + (i + 1));
            }
            System.out.println("end.");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

    運行結果:

    

由兩次運行結果能夠看出for循環後面的end沒有輸出.

 

四 . 中止線程(睡眠中止)

       先中止,在進入sleep

public class MyThread extends Thread {

    @Override
    public void run() {
        super.run();
        try {
            for(int i = 0 ; i < 100000 ; i ++){
                System.out.println(" i = " + (i + 1));
            }
            System.out.println("Thread run begin");
            Thread.sleep(200000);
            System.out.println("Thread run end");
        }catch (Exception e){
            System.out.println("end in sleep ." + this.interrupted());
            e.printStackTrace();
        }
    }

}
public class Test {
    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            myThread.setName("test");
            myThread.interrupt();
            System.out.println("線程名字 :" + myThread.getName());
            System.out.println("線程是否中斷 : " + myThread.interrupted());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

運行結果:

注:若是先進入sleep,在中止線程,會進入catch語句,而且清除狀態值,使之變爲false.

     先中止在進入sleep,也會進入catch,可是不會清除狀態值.

五 . 暴力中止

      暴力中止即直接使用stop()方法    

public class MyThread extends Thread {

            private int i = 0 ;
            @Override
            public void run() {
                super.run();
                try {
                    while(true){
                        i ++;
                        System.out.println(" i = " + i );
                        Thread.sleep(1000);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }

        }

        

public class Test {
            public static void main(String[] args) {
                try {
                    MyThread myThread = new MyThread();
                    myThread.start();
                    myThread.setName("test");
                    Thread.sleep(8000);
                    myThread.stop();
                    System.out.println("線程名字 :" + myThread.getName());
                    System.out.println("線程是否中斷 : " + myThread.interrupted());
                } catch (Exception e) {
                    e.printStackTrace();
                }
        
            }
        }

    運行結果:

    

 

        注 : 方法stop和java.lang.ThreadDeath異常

              在調用stop()方法時,會拋出java.lang.ThreadDeath異常,可是通常狀況下不須要特地去捕獲該異常 

              方法stop()已經做廢了,由於若是強制讓線程中止則有可能使一些清理性的工做沒法完成,另一種狀況就是對鎖定的對象進行了解鎖,致使數據得不到同步的處理,出現數據不一致的問題.

 

六 .  釋放鎖的不良影響

        使用stop()方法中止線程釋放鎖之後會給數據形成不一致的結果,若是出現這樣的狀況,程序處理的數據就有可能遭到破壞,最終致使程序執行的流程出錯.

public class Start {
    private String a = "a";
    private String b = "b";

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    synchronized public void printString(String username , String pswd){
        try{
            a = username;
            Thread.sleep(1000);
            b = pswd;
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

 

public class MyThread extends Thread {

    private Start start;

    public MyThread(Start startObject){
        super();
        start = startObject;
    }

    @Override
    public void run(){
        start.printString("b","bb");
    }
}
public class Test {
    public static void main(String[] args) {
        try {
            Start start = new Start();
            MyThread myThread = new MyThread(start);
            myThread.start();
            Thread.sleep(500);
            myThread.stop();
            System.out.println("name = " + start.getA() + " ; password = " + start.getB());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

運行結果:

    

因爲stop()方法已經在JDK中唄標記爲做廢的方法,因此他在功能上具備缺陷,儘可能不要在程序中使用.

 

七 .  使用return中止線程

        將方法interrupt()和return結合使線程中止.

public class MyThread extends Thread {

    @Override
    public void run(){
        while(true){
            if(this.isInterrupted()){
                System.out.println("Thread ended.");
                return;
            }
            System.out.println("time = " + System.currentTimeMillis());
        }
    }
}
public class Test {
    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            Thread.sleep(2000);
            myThread.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

運行結果:

 

雖然有多種方法使線程中止,可是仍是建議經過catch語句塊中止線程,由於catch語句塊能夠拋出異常到上層.

相關文章
相關標籤/搜索