在前文中咱們已經學習了:線程的基本狀況、如何建立多線程、線程的生命週期。利用已有知識咱們已經能夠寫出如何利用多線程處理大量任務這樣簡單的程序。可是當應用場景複雜時,咱們還須要從管理控制入手,更好的操縱多線程。在第一節中咱們講過,使用多線程的好處之一就是咱們能夠經過編碼和已有類庫更好的管理和控制多線程。接下來我會詳細的介紹如何管理多線程,包括:對線程的等待、守護線程、線程的睡眠、線程的忽然中止、線程的讓步、線程的優先級等。因爲內容比較多,本節先介紹前兩部分:對線程的等待、守護線程html
一、線程的等待java
咱們經常對同一件事情進行切割,分紅多幹件小的事情後,再開闢多條線程來處理(有點分治的味道)。在多件事情處理完成以後咱們須要再統一的處理。這樣說有點枯燥:好比咱們要導出一份文件,這個文件的行數很是多大概幾十萬行數據。直接導出也能夠,會致使系統卡一下,嚴重一點的可能會超時。這時候怎麼辦呢?咱們能夠分紅若干份,好比每五千條數據是一份數據,而後用一條線程去導出到文件中,這樣就會生成若干份文件。當全部的文件都導出後,咱們把這些數據彙總一下就OK了。可是這裏有一個問題,何時全部線程都導完數據了呢?咱們總不能一個一個的去檢查文件是否存在吧。多線程
這裏java爲咱們提供了一個專門用於等待的方法Join().當某條線程執行了其餘線程的join()方法之後,當前線程就會阻塞,直到其餘線程執行結束之後,才能夠運行。學習
以下述代碼:編碼
1 public class newThread extends Thread 2 { 3 public newThread(String name) 4 { 5 super(name); 6 } 7 public void run() 8 { 9 int i=100; 10 while(i-->0) 11 { 12 sleep(100); 13 } 14 } 15 16 public static void main(String args)throws Exception 17 { 18 Thread son_1=new newThread("thread-1"); 19 Thread son_2=new newThread("thread-2"); 20 son_1.start(); 21 son_2.start(); 22 son_1.join();//注意這裏 23 son_2.join(); 24 System.out.println("all threads is over") 25 } 26 }
咱們分別啓動thread 1 和thread 2。這兩條線程會分別運行,互相不影響,而後咱們用主線程來等待線程1,直到它結束,咱們纔開始等待線程2。若是線程1比線程2的用時長的話,再咱們等待完線程1 後,線程2將無需等待,直接輸出結果。
join方法共有三種形式的重載spa
1 join() 2 join(long millis)//
3 join(long millis,int nanos)//millis 毫秒 nanos微秒
第一個方法時直到等待線程結束才繼續向下運行,第二和第三個方法則是在限定時間內等待,若是時間結束將不會繼續等待(能夠用於超時判斷),注意第三個方法並不經常使用,這裏主要是由於java和硬件對時間的把控根本難以精確到微秒級,因此並不能很準確到控制。線程
二、守護線程設計
守護線程(Daemon Thread)又叫作精靈線程、後臺線程。乍一聽守護二字,以爲好像很厲害的意思,像是在保護其餘線程的線程,其實很簡單,並無那麼玄。全部的語言設計,都是爲了更方便的使用。(防盜鏈接:本文首發自王若伊_恩賜解脫http://www.cnblogs.com/jilodream/ )code
設想這樣一個場景:在一個考場內,考生們都在埋頭答卷,除了考生,還有監考老師,他的職責就是爲了維護考場的秩序,對於有困難的考生提供幫助。當全部的考生都交卷後(或者時間到了之後,考生被強制交卷(結束線程)),這個監考老師的義務已經完成,無需繼續運行。簡而言之,這個監考老師是爲了其餘學生提供後臺服務的,當全部的考生都已經停筆後,老師的義務也已經結束了,能夠退場了。htm
有些人看到這裏,可能會以爲,這還不簡單,咱們只要如線程等待讓老師等待全部的學生都結束以後,不就能夠了麼?!這個回答對也不對。對的是老師的線程的確是在等待學生線程結束,不對的地方是老師線程在等待的同時,還在提供服務,並非全部學生停筆後收卷這麼簡單。在Jvm中有一個全部開發者都熟悉的線程GC,它就是在其餘線程運行的同時,默默的提供服務,當其餘線程結束後,他又默默的退場。
以下代碼
1 public class newThread extends Thread 2 { 3 public newThread(String name) 4 { 5 super(name); 6 } 7 public void run() 8 { 9 int i=100; 10 while(i-->0) 11 { 12 sleep(100); 13 } 14 } 15 16 public static void main(String args)throws Exception 17 { 18 Thread son_1=new newThread("thread-1"); 19 Thread son_2=new newThread("thread-2"); 20 Thread daemonThread=new newThread("thread-daemonThread"); 21 son_1.start(); 22 son_2.start(); 23 24 daemonThread.setDaemon(true);//注意看這裏 25 daemonThread.start(); 26 son_1.join(); 27 son_2.join(); 28 System.out.println("all son_threads is over") 29 } 30 } 31 32 class DaemonThread 33 { 34 public DaemonThread(String name) 35 { 36 super(name); 37 } 38 public void run() 39 { 40 int i=1000; 41 while(i-->0) 42 { 43 sleep(100); 44 } 45 } 46 }
在代碼中 Daemonthread線程被設置爲後臺線程,則當主線程等待子線程結束後, Daemonthread線程也會結束,不會繼續運行。咱們能夠用這種方式設置一種線程,專門用來維護其餘線程的正常運行,好比後臺計數,計時,查詢各個客戶端是否保持在線(心跳),推送事件等。
java還專門提供了 IsDaemon()的方法來判斷這個線程是否爲後臺線程。
這裏有一點注意的是,若是要設置一個線程爲後臺線程,必需要在這個線程尚未開始「就緒」(start())時設置,不然會引起非法的線程狀態異常