java多線程(1) ----- java多線程技能(下)

(歡迎關注微信公衆號:深入Java底層)

1、停止線程

1.1 停止不了的線程

調用interrupt()方法僅僅是在當前線程中打了一個停止的標記,並不是真的停止線程

1.2 判斷線程是否是停止狀態

this.interrupted():測試當前線程是否已經是中斷狀態,執行後具有將狀態標誌清除爲false的功能。

package t12;

publicclass MyThread extends Thread {

       @Override

       publicvoid run() {

              super.run();

              for(int i=0;i<500000;i++){

                     System.out.println("i="+ (i+1));

              }

       }

}

package t12;

publicclass Run2 {

       /**

        * @param args

        */

       publicstaticvoidmain(String[] args) {

         //thread.interrupt();

              Thread.currentThread().interrupt();

              System.out.println("是否停止1 =" + Thread.interrupted());

              System.out.println("是否停止2 =" + Thread.interrupted());

              System.out.println("end!");

       }

}

運行結果:

//thread.interrupt();

是否停止1 =false

是否停止2 =false

end!

// Thread.currentThread().interrupt();

是否停止1 =true

是否停止2 =false

end!

this.isInterrupted():測試線程Thread對象是否已經是中斷狀態,但不清除狀態標誌。

package t12;

publicclass Run3 {

       /**

        * @param args

        */

       publicstaticvoidmain(String[] args) {

              try {

                     MyThreadthread = new MyThread();

                     thread.start();

                     Thread.sleep(1000);

                     thread.interrupt();

                     //Thread.currentThread().interrupt();

                     System.out.println(" 是否停止1 =" +thread.isInterrupted());

                     System.out.println(" 是否停止2 =" +thread.isInterrupted());

              } catch(InterruptedException e) {

                     System.out.println("maincatch");

                     e.printStackTrace();

              }

              System.out.println("end!");

       }

}

運行結果:

//thread.interrupt();

是否停止1 =true

是否停止2 = true

end!

1.3 異常法停止的線程

在線程中用for語句來判斷一下線程是否停止狀態,如果是停止狀態,則後面的代碼不再運行即可。但如果for語句下面還有語句,還是會繼續運行。使用“拋異常”的方法可以解決上面的問題,參看如下代碼

package t13_1;

publicclass Run {

       publicstaticvoidmain(String[] args) {

              try {

                     MyThreadthread = new MyThread();

                     thread.start();

                     Thread.sleep(2000);

                     thread.interrupt();

              } catch(InterruptedException e) {

                     System.out.println("maincatch");

                     e.printStackTrace();

              }

              System.out.println("end!");

       }

}

package t13_1;

publicclass Run {

       publicstaticvoidmain(String[] args) {

              try {

                     MyThreadthread = new MyThread();

                     thread.start();

                     Thread.sleep(2000);

                     thread.interrupt();

              } catch(InterruptedException e) {

                     System.out.println("maincatch");

                     e.printStackTrace();

              }

              System.out.println("end!");

       }

      

       /**

        * 運行結果:

        * ...

           i=352988

              i=352989

              i=352990

              i=352991

              i=352992

              i=352993

              已經停止狀態了,我要退出了

              end!

              MyThread.javarun方法中的catch了!

              java.lang.InterruptedException

                     att13_1.MyThread.run(MyThread.java:11)

        *

        */

}

1.4 在沉睡中停止

如果在sleep狀態下停止某一線程,會進入catch語句,並且清除停止狀態值,使之變成false;

package t14;

publicclass MyThread extends Thread {

       @Override

       publicvoid run() {

              super.run();

              try{

                     System.out.println("runbegin");

                     Thread.sleep(200000);

                     System.out.println("runend");

              }catch(InterruptedExceptione){

                     System.out.println("在沉睡中被停止!進入catch!" + Thread.interrupted());

                     e.printStackTrace();

              }

       }

}

package t14;

publicclass Run {

       /**

        * @param args

        */

       publicstaticvoidmain(String[] args) {

              try {

                     MyThreadthread = new MyThread();

                     thread.start();

                     Thread.sleep(200);

                     thread.interrupt();

              } catch(InterruptedException e) {

                     System.out.println("maincatch");

                     e.printStackTrace();

              }

              System.out.println("end!");

       }

       /**

        * 運行結果:

        * run begin

          end!

             在沉睡中被停止!進入catch!false

          java.lang.InterruptedException: sleepinterrupted

                at java.lang.Thread.sleep(Native Method)

                at t14.MyThread.run(MyThread.java:10)

        *

        */

}

如果先interrupt()然後再sleep,也會進入catch語句,並且清除停止狀態值,使之變成false。

package t15;

publicclass MyThread extends Thread {

       @Override

       publicvoid run() {

              super.run();

              try{

                     for(inti=0;i<100000;i++){

                            System.out.println("i="+(i+1));

                     }

                     System.out.println("runbegin");

                     Thread.sleep(200000);

                     System.out.println("runend");

              }catch(InterruptedExceptione){

                     System.out.println("先停止!再遇到了sleep!進入catch!"+ Thread.interrupted());

                     e.printStackTrace();

              }

       }

       /**

        * interrupt()然後再sleep,也會進入catch語句,並且清除停止狀態值。

        *

        */

}

package t15;

publicclass Run {

       /**

        * @param args

        */

       publicstaticvoidmain(String[] args) {

              MyThreadthread = new MyThread();

              thread.start();

              thread.interrupt();

              System.out.println("end!");

       }

      

       /**

        * 運行結果:

    …………….

        * i=99995

              i=99996

              i=99997

              i=99998

              i=99999

              i=100000

              runbegin

              先停止!再遇到了sleep!進入catch!false

              java.lang.InterruptedException:sleep interrupted

                     atjava.lang.Thread.sleep(Native Method)

                     att15.MyThread.run(MyThread.java:13)

        *

        */

}

1.5 使用return停止線程

    將方法interrupt()與return結合使用也能實現停止線程的效果。不過還是建議使用“拋異常”的方法來實現線程的停止,因爲在catch塊中還可以將異常向上拋,使線程停止的事件得以傳播。

2. yield方法

yield()方法的作用是放棄當前的CPU資源,將它讓給其他的任務去佔用CPU執行時間。但放棄的時間不確定,有可能剛剛放棄,馬上又獲得CPU時間片。

3. 線程的優先級

在操作系統中,線程可以劃分優先級,優先級較高的線程得到

的CPU資源較多,也就是CPU優先執行優先級較高的線程對象中任務。

在Java中,線程的優先級具有繼承性,比如A線程啓動B線程,則B線程的優先級與A是一樣的。如果A線程的優先級被更改,B線程將繼承更改。

package t18;

publicclass MyThread1 extends Thread {

       @Override

       publicvoid run() {

              System.out.println("MyThread1run priority=" + this.getPriority());

              MyThread2thread2 = new MyThread2();

              thread2.start();

       }

 

}

package t18;

publicclass MyThread2 extends Thread {

       @Override

       publicvoid run() {

              System.out.println("MyThread2run priority=" + this.getPriority());

       }

}

package t18;

publicclass Run {

       /**

        * @param args

        */

       publicstaticvoidmain(String[] args) {

              System.out.println("mainthread begin priority=" + Thread.currentThread().getPriority());

//           Thread.currentThread().setPriority(6);

              System.out.println("mainthread begin priority=" + Thread.currentThread().getPriority());

              MyThread1thread1 = new MyThread1();

              thread1.start();

       }

    /**

     * 運行結果:

     *  main thread begin priority=5

              mainthread begin priority=5

              MyThread1run priority=5

              MyThread2run priority=5

     *

     * 去掉註釋,運行結果:

     *  main thread begin priority=5

              mainthread begin priority=6

              MyThread1run priority=6

              MyThread2run priority=6

     *

     *

     * java中,線程的優先級具有繼承性,比如A線程啓動B線程,則B線程的優先級與A是一樣的。

     */

}

線程的優先級具有一定的規則性,也就是CPU儘量將執行資源讓給優先級比較高的線程,但優先級較高的線程並不一定每一次都先執行完,線程的優先級還具有“隨機性”。優先級高的運行得快,但是測試的時候好多次並沒有更快。

4. 守護線程

在Java線程中兩種線程,一種是用戶線程,另一種是守護線程。

守護線程是一種特殊的線程,當線程中不存在非守護線程了,則守護線程自動銷燬。典型的守護線程就是垃圾回收線程,當進程中沒有非守護線程了,則垃圾回收線程也就沒有存在的必要了,自動銷燬。Daemon的作用是爲其他線程的運行提供便利服務,守護線程最典型的應用就是GC(垃圾回收器),它就是一個很稱職的守護者。

(歡迎關注微信公衆號:深入Java底層)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章