【搞懂Java多線程之二】多線程調度及守護進程

來源:互聯網
上載者:User

標籤:java多線程   進程調度   守護進程   

在前一篇文章中說到,所有處在就緒狀態中的線程,作業系統會選擇優先順序最高的優先進行調度,那麼是不是優先順序高的線程就一定比優先順序低的線程先執行呢?線程的優先順序又是怎麼劃分的呢?這篇文章,樓樓就要來說說這個問題啦!歡迎關注我的個人部落客頁www.anycodex.com

1.線程的優先順序
在Java中,線程優先順序的範圍為0-10,整數值越大,說明優先順序更高。

  • 幾個相關的宏定義:
MAX_PRIORITY 10,最高優先順序

MIN_PRIORITY 1,最低優先順序

NORM_PRIORITY 5,預設優先順序

  • 相關的介面
setPriority(int x),設定線程的優先順序

getPriority(),擷取線程的優先順序

既然線程之間有優先順序,那是不是優先順序高的就一定比優先順序低的線程先執行呢?答案是不是的。只能說優先順序高的線程有更大的可能性獲得CPU,但這並不意味著就一定會先執行。

小夥伴們,我們下面來看一段代碼的例子吧,呼呼(~ o ~)~zZ

package net.mindview.util;//第一步、實現Runnable介面class MyThreadRunning implements Runnable{        //第二步、重寫run方法    public void run() {        for (int i = 0; i <= 3; i++) {            System.out.println(Thread.currentThread().getName());        }    }}public class MyThread {    public static void main(String[] args) {                //第三步、執行個體化自訂的線程類對象        MyThreadRunning mtr1 = new MyThreadRunning();        MyThreadRunning mtr2 = new MyThreadRunning();        MyThreadRunning mtr3 = new MyThreadRunning();        //第四步、執行個體化一個Thread類對象並將自訂的線程類對象作為參數傳入,後面一個參數為線程名        Thread thread1 = new Thread(mtr1, "Thread 1 is running");        Thread thread2 = new Thread(mtr2, "Thread 2 is running");        Thread thread3 = new Thread(mtr3, "Thread 3 is running");                thread1.setPriority(Thread.MAX_PRIORITY);        thread2.setPriority(Thread.MIN_PRIORITY);        thread3.setPriority(Thread.NORM_PRIORITY);        //第五步、調用start方法啟動線程        thread1.start();        thread2.start();        thread3.start();    }}
運行結果:

Thread 1 is running
Thread 1 is running
Thread 2 is running
Thread 1 is running
Thread 3 is running
Thread 3 is running
Thread 3 is running
Thread 3 is running
Thread 1 is running
Thread 2 is running
Thread 2 is running
Thread 2 is running

噹噹當,小夥伴們是不是明白了呢?優先順序高的線程原來並不一定會先執行啊?只是有比較大的可能會獲得CPU調度。小夥伴們,可能會問,都設定優先順序了,還是不能保證線程按照我所希望的先後順序去執行,我還有什麼招呢?嗯,看完下面的內容,你就能學到一些招了,它就是我們的線程調度。

2.線程調度
關於線程調度,我們需要瞭解,只有良好的調度,才能發揮良好的系統效能,提高程式的執行效率。但是,再怎麼好的調度,也都無法精確的控製程序的運行。通常我們採用線程調度的方法主要有sleep,yield和join等方法。下面我們一個一個看哈!

sleep()方法,sleep就如英文意思所釋,睡眠。當某個程式進入睡眠狀態時,就會將CPU資源交給其他線程,而當休眠時間到時,程式又自動由阻塞狀態進入就緒狀態,等待CPU資源的調度。sleep()參數是毫秒級的,如sleep(1000)是讓線程休眠1s。調用這個方法的時候,需要捕獲InterruptedException異常。看下面的代碼吧

package net.mindview.util;//第一步、實現Runnable介面class MyThreadRunning implements Runnable{        //第二步、重寫run方法    public void run() {        for (int i = 0; i <= 3; i++) {            System.out.println(Thread.currentThread().getName());            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }}public class MyThread {    public static void main(String[] args) {                //第三步、執行個體化自訂的線程類對象        MyThreadRunning mtr1 = new MyThreadRunning();        MyThreadRunning mtr2 = new MyThreadRunning();        MyThreadRunning mtr3 = new MyThreadRunning();        //第四步、執行個體化一個Thread類對象並將自訂的線程類對象作為參數傳入,後面一個參數為線程名        Thread thread1 = new Thread(mtr1, "Thread 1 is running");        Thread thread2 = new Thread(mtr2, "Thread 2 is running");        Thread thread3 = new Thread(mtr3, "Thread 3 is running");                //第五步、調用start方法啟動線程        thread1.start();        thread2.start();        thread3.start();    }}
運行結果:

Thread 2 is running
Thread 3 is running
Thread 1 is running
Thread 3 is running
Thread 2 is running
Thread 1 is running
Thread 2 is running
Thread 1 is running
Thread 3 is running
Thread 3 is running
Thread 2 is running
Thread 1 is running

從運行結果中可以看出,線程無法精確的控制先後順序。每次運行結果都有可能不一樣。

  • yield方法
yield方法也像英文的意思一樣,就是讓步。暫停當前線程,讓出CPU已耗用時間,進入就緒狀態,從而讓其他線程獲得CPU時間。不過對於搶佔式作業系統沒有什麼意義,或者說沒有效果。

package net.mindview.util;//第一步、實現Runnable介面class MyThreadRunning1 implements Runnable{        //第二步、重寫run方法    public void run() {        for (int i = 0; i <= 3; i++) {            System.out.println(Thread.currentThread().getName());        }    }}//第一步、實現Runnable介面class MyThreadRunning2 implements Runnable{        //第二步、重寫run方法    public void run() {        for (int i = 0; i <= 3; i++) {            System.out.println(Thread.currentThread().getName());            Thread.yield();        }    }}public class MyThread {    public static void main(String[] args) {                //第三步、執行個體化自訂的線程類對象        MyThreadRunning1 mtr1 = new MyThreadRunning1();        MyThreadRunning2 mtr2 = new MyThreadRunning2();        //第四步、執行個體化一個Thread類對象並將自訂的線程類對象作為參數傳入,後面一個參數為線程名        Thread thread1 = new Thread(mtr1, "Thread 1 is running");        Thread thread2 = new Thread(mtr2, "Thread 2 is running");                //第五步、調用start方法啟動線程        thread1.start();        thread2.start();    }}
運行效果: 如果不加yield的可能的運行結果:

Thread 1 is running Thread 1 is running
Thread 2 is running Thread 2 is running
Thread 1 is running Thread 1 is running
Thread 2 is running Thread 1 is running
Thread 1 is running Thread 1 is running
Thread 2 is running Thread 2 is running
Thread 1 is running Thread 2 is running
Thread 2 is running Thread 2 is running

從運行效果中可以看出,線程2每執行一次就會讓出CPU資源一次,但也只是可能的運行結果。

  • join方法
join方法的作用可能從英文意思上理解不是那麼簡單,那其實呢,join方法的作用是想讓一個線程等待另一個線程執行完畢後再繼續執行。可以添加參數,long類型的毫秒,等待該進程終止最長為多少秒。如thread.mt()就是等thread線程執行完之後,再執行其他的程式。我們可以看下面的代碼:
package net.mindview.util;//第一步、繼承Thread類class MyThreadRunning extends Thread{    //建構函式    public MyThreadRunning() {        super("My Thread");    }        //第二步、重寫run方法    public void run() {        for (int i = 0; i <= 3; i++) {            System.out.println("建立一個線程" + getName()+i);            try {                sleep(1000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }                    }    }}public class MyThread {    public static void main(String[] args) {                //第三步、執行個體化自訂的線程類對象        MyThreadRunning mtr = new MyThreadRunning();                        //第四步、調用start方法從而啟動run方法        mtr.start();                  try {            mtr.join();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }                System.out.println("mtr你執行完了是吧?我是主線程,我要來列印了。");    }}
運行結果:

建立一個線程My Thread0
建立一個線程My Thread1
建立一個線程My Thread2
建立一個線程My Thread3
mtr你執行完了是吧?我是主線程,我要來列印了。

3.守護進程
守護進程也叫後台進程,是一種為其他線程提供服務的一種線程。當虛擬機器檢測到沒有使用者進程執行了的話,即使還有後台進程,JVM也有可能會退出的。

相關介面:

setDaemon(boolean)將一個線程設定為後台進程;

Thread.isDaemon()判斷一個線程是否為後台進程。

我們可以來看下面的代碼:
package net.mindview.util;//第一步、繼承Thread類public class MyThread {     public static void main(String[] args) {             Thread t1 = new MyCommon();             Thread t2 = new Thread(new MyDaemon());             t2.setDaemon(true);        //設定為守護線程             t2.start();             t1.start();     } } class MyCommon extends Thread {     public void run() {             for (int i = 0; i < 5; i++) {                     System.out.println("線程1第" + i + "次執行!");                     try {                             Thread.sleep(7);                     } catch (InterruptedException e) {                             e.printStackTrace();                     }             }     } } class MyDaemon implements Runnable {     public void run() {             for (long i = 0; i < 9999999L; i++) {                     System.out.println("後台線程第" + i + "次執行!");                     try {                             Thread.sleep(7);                     } catch (InterruptedException e) {                             e.printStackTrace();                     }             }     } }
運行結果:

線程1第0次執行!
後台線程第0次執行!
後台線程第1次執行!
線程1第1次執行!
線程1第2次執行!
後台線程第2次執行!
線程1第3次執行!
後台線程第3次執行!
線程1第4次執行!
後台線程第4次執行!
後台線程第5次執行!

同學們,由運行結果中是不是可以看出,後台線程還沒有執行完呢,程式就退出了。



以上就是我們關於Java多線程的第二部分內容了,總結一下,這篇文章主要講Java多線程的調度問題。調度方法主要有睡眠啊,讓步啊,以及join啊之類的。但是要清楚,無論程式員怎麼進行調度,也都無法實現線程的精確控制。當時良好的線程調度可以提高程式啟動並執行效率。最後我們講到守護線程,也就是後台線程,這裡需要注意的事,虛擬機器檢測到沒有使用者線程運行了的話,不管有沒有後台線程,都會退出。嗯,就這麼多了,小夥伴們,都掌握了嗎?下面一篇文章,我們要學習的是經典問題,生產者和消費者之類的線程同步問題,加油加油加油,未完待續哦~~~

【搞懂Java多線程之二】多線程調度及守護進程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.