線程的狀態轉換:java
新建狀態:new出一個線程,線程尚未開始運行,當線程處於新建狀態時,程序還沒ide
有運行線程中的代碼。spa
就緒狀態:當線程對象調用start()方法即啓動了線程,start()方法建立線程運行的系統資源,並調度線程運行run()方法。當start()方法返回後,線程就處於就緒狀態。線程
處於就緒狀態的線程並不必定當即運行run()方法,線程還必須同其餘線程競爭CPU時間,只有得到CPU時間才能夠運行線程。對處於就緒狀態的線程是由Java運行時系統的線程調度程序(thread scheduler)來調度的。code
運行狀態:當線程得到CPU時間後,它才進入運行狀態,真正開始執行run()方法.對象
阻塞狀態:資源
線程運行過程當中,可能因爲各類緣由進入阻塞狀態:字符串
(1)線程經過調用sleep方法進入睡眠狀態;虛擬機
(2)線程調用一個在I/O上被阻塞的操做,即該操做在輸入輸出操做完成以前不會返回到它的調用者;it
(3)線程試圖獲得一個鎖,而該鎖正被其餘線程持有;
(4)線程在等待某個觸發條件;
所謂阻塞狀態是正在運行的線程沒有運行結束,暫時讓出CPU,這時其餘處於就緒狀態的線程就能夠得到CPU時間,進入運行狀態。
死亡狀態
有兩個緣由會致使線程死亡:
(1)run方法正常退出而天然死亡,
(2)一個未捕獲的異常終止了run方法而使線程猝死。
線程調度:
線程調度—線程休眠:線程睡眠是線程主動讓出CPU讓其餘線程執行,線程從運行狀態切換爲阻塞狀態,線程休眠是其餘線程執行的有效方法,可是休眠時間到休眠線程未必執行,它的執行依靠CPU的調度。
/** * 睡眠 * 一個計數器,計數到 100,在每一個數字之間暫停 1 秒,每隔 10 個數字輸出一個字符串 */ public class ThreadSleep { public static void main(String[] args) { new Thread(new Runnable() { public void run() { for(int i = 0; i < 100; i++){ if((i) % 10 ==0 ){ System.out.println("************"); } try { Thread.sleep(1); System.out.println("i的值是:" + i); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
線程調度—線程讓步:運行狀態的線程讓出CPU資源,可是然給誰不知道,僅僅是讓出,也有多是本身,線程從運行狀態切換爲阻塞狀態。
public class ThreadYield { public static void main(String[] args) { Thread t1 = new MyThread1(); Thread t2 = new Thread(new MyRunnable()); t2.start(); t1.start(); } static class MyThread1 extends Thread { public void run() { for (int i = 0; i < 10; i++) { System.out.println("線程1第" + i + "次執行!"); } } } static class MyRunnable implements Runnable { public void run() { for (int i = 0; i < 10; i++) { System.out.println("線程2第" + i + "次執行!"); Thread.yield(); } } } } //執行結果(能夠看出線程線程1執行完後線程1開始執行) 線程2第0次執行! 線程1第0次執行! 線程1第1次執行! 線程1第2次執行! 線程1第3次執行! 線程1第4次執行! 線程1第5次執行! 線程1第6次執行! 線程1第7次執行! 線程1第8次執行! 線程1第9次執行! 線程2第1次執行! 線程2第2次執行! 線程2第3次執行! 線程2第4次執行! 線程2第5次執行! 線程2第6次執行! 線程2第7次執行! 線程2第8次執行! 線程2第9次執行!
線程調度—線程合併:如今有線程A、線程B,線程合併是將線程A、B合二爲一,線程A先執行,而後調用join方法,則線程B開始執行,等B執行完成後A再接着上次繼續執行。應用場景是當一個線程必須等待另外一個線程執行完畢才能執行時可使用join方法。
public class ThreadJoin extends Thread { public static void main(String[] args) { Thread t1 = new MyThread2(); t1.start(); for (int i = 0; i < 10; i++) { System.out.println("主線程第" + i + "次執行!"); if (i > 2) try { //t1 線程合併到主線程中,主線程中止執行過程,轉而執行 t1 線程, 直到 t1 執行完畢後繼續。 t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class MyThread2 extends Thread { public void run() { for (int i = 0; i < 4; i++) { System.out.println("線程 1 第" + i + "次執行!"); } } } //執行結果 主線程第0次執行! 主線程第1次執行! 主線程第2次執行! 主線程第3次執行! 線程 1 第0次執行! 線程 1 第1次執行! 線程 1 第2次執行! 線程 1 第3次執行! 主線程第4次執行! 主線程第5次執行! 主線程第6次執行! 主線程第7次執行! 主線程第8次執行! 主線程第9次執行!
線程調度—線程守候:守護線程在沒有用戶線程可服務時自動離開,再java虛擬機中當正在運行的線程都是守護線程時,Java虛擬機退出。調用線程對象的方法setDaemon(true),則能夠將其設置爲守護線程,該方法必須在線程調用前執行。
public class ThreadDaemon { public static void main(String[] args) { Thread t1 = new MyCommon(); Thread t2 = new MyDaemon(); t2.setDaemon(true); t1.start(); t2.start(); } } class MyCommon extends Thread { public void run() { for (int i = 0; i < 5; i++) { System.out.println("線程MyCommon第" + i + "次執行!"); try { Thread.sleep(7); } catch (InterruptedException e) { e.printStackTrace(); } } } } class MyDaemon extends Thread { public void run() { for (int i = 0; i < 400; i++) { System.out.println("線程 MyDaemon 第" + i + "次執行!"); try { Thread.sleep(7); } catch (InterruptedException e) { e.printStackTrace(); } } } } //執行結果(MyDaemon線程尚未執行完成變退出) 線程MyCommon第0次執行! 線程 MyDaemon 第0次執行! 線程 MyDaemon 第1次執行! 線程MyCommon第1次執行! 線程MyCommon第2次執行! 線程 MyDaemon 第2次執行! 線程MyCommon第3次執行! 線程 MyDaemon 第3次執行! 線程MyCommon第4次執行! 線程 MyDaemon 第4次執行! 線程 MyDaemon 第5次執行!
線程調度—線程優先級:線程的有限執行順序,優先級1~10,數值越大優先級越高。在一個線程中開啓另一個新線程,則新開線程稱爲該線程的子線程,子線程初始優先級與父線程相同。
注意:線程的優先級仍然沒法保障線程的執行次序。只不過,優先級高的線程獲取CPU資源的機率較大,優先級低的並不是沒機會執行。
public class ThreadPriority { public static void main(String[] args) { Thread threadA = new Thread(new ThreadA()); Thread threadB = new Thread(new ThreadB()); threadA.setPriority(10); threadB.setPriority(1); threadB.start(); threadA.start(); } } class ThreadA extends Thread { @Override public void run() { for (int i = 0; i < 5; i++) { System.out.println(" A線程第" + i + "次執行"); } } } class ThreadB extends Thread { @Override public void run() { for (int j = 0; j < 10; j++) { System.out.println("B線程第" + j + "次執行"); } } } //執行結果 B線程第0次執行 B線程第1次執行 A線程第0次執行 B線程第2次執行 A線程第1次執行 A線程第2次執行 B線程第3次執行 B線程第4次執行 B線程第5次執行 B線程第6次執行 B線程第7次執行 B線程第8次執行 B線程第9次執行 A線程第3次執行 A線程第4次執行