標籤:
1 更多內容可以查看本人另外一個部落格: http://blog.csdn.net/unikylin/article/details/45050823
1.線程自身資訊
線程啟動並執行過程會產生很多資訊,這些資訊都儲存在Thread類中的成員變數裡面,常見的有:
a.線程的ID是唯一標識getId()
b.線程的名稱:getName(),如果不設定線程名稱預設為“Thread-xx”
c.線程的優先順序:getPriority,線程優先順序從1-10,其中數字越大表示優先順序別越高,同時獲得JVM調度執行的可能性越大,JDK內建了三種常見的狀態:
1 //最小優先順序2 public final static int MIN_PRIORITY = 1;3 4 //一般優先順序5 public final static int NORM_PRIORITY = 5;6 7 //最大優先順序8 public final static int MAX_PRIORITY = 10;
一般不推薦設定線程的優先順序,如果進行設定了非法的優先順序程式就會出現IllegalArgumentException異常。
2.線程的幾個狀態1.Java線程有六種狀態
1 public enum State { 2 //線程剛建立 3 NEW, 4 5 //在JVM中正在啟動並執行線程 6 RUNNABLE, 7 8 //線程處於阻塞狀態,等待監視鎖,可以重新進行同步代碼塊中執行 9 BLOCKED,10 11 //等待狀態12 WAITING,13 14 //調用sleep() join() wait()方法可能導致線程處於等待狀態15 TIMED_WAITING,16 17 //線程執行完畢,已經退出18 TERMINATED;19 }
上面六種狀態圖如下:
2.線程狀態的解釋
1.當線程繼承Thread或者實現了Runnable建立了線程對象後,當new線程對象過後線程就進入了初始的狀態。
2.當線程對象調用了start()方法的時候,線程啟動進入可啟動並執行狀態。
3.線程進入可運行狀態後,如果邏輯完成那麼線程將會終結,如果沒有執行完畢中間JVM分配時間片用完,將進入可運行狀態,一旦線程被JVM選中則立即執行。
4.運行狀態的情況比較複雜
第一:線程如果執行run() main()方法結束後,完成邏輯,線程就進入Terminated
第二:當線程調用sleep()或者join()方法就會進入Blocked狀態,但是要注意的是阻塞的線程是不釋放當前所佔有的系統資源,當sleep()結束或者join()等待其他線程來到,當前線程則進入Runnable狀態等待JVM分配資源。
第三:當線程進入Runnable狀態,但是還沒有開始啟動並執行時候,此時發現需要的資源處於同步狀態synchronized,這個時候線程將會進入Time waiting,JVM會使用隊列對這些線程進行控制,既先進行Time waiting的線程會先得到JVM資源進行執行進入Waiting
第四:如果處於Runnable的線程調用yield()讓出JVM資源,那麼就會進入New狀態和其他New狀態線程進行競爭重新進入Runnable
第五:如果當前線程調用wait()方法,則當前線程進入Time waiting但是這個時候當前線程會釋放所佔有的JVM資源,進入這個狀態過後是不能自動喚醒的,必須調用notify()或者notifyAll()方法,線程進入Waiting。
3.案例解釋
案例:用案例解釋線程的六種運行狀態,其中Pig類實現Runnable介面,邏輯是列印當前啟動並執行線程資訊,每隔一秒列印一次。在Main方法中啟動十個Pig線程設定相應的線程優先順序別,並且將初始的線程狀態儲存到線程狀態數組中,在啟動並執行過程判斷當前線程狀態和初始狀態是否相同,如果不同則列印當前線程的資訊儲存到記錄檔中。
1 class Pig implements Runnable { 2 3 @Override 4 public void run() { 5 for (int i = 0; i < 10; i++) { 6 try { 7 //線程進行休眠一秒 8 TimeUnit.SECONDS.sleep(1); 9 } catch (InterruptedException e) {10 e.printStackTrace();11 }12 //列印當前執行線程資訊13 System.out.println("ThreadName : " + Thread.currentThread().getName());14 }15 }16 }17 18 public class App {19 public static void main(String[] args) throws Exception {20 // 建立現成數組21 Thread[] taskArr = new Thread[10];22 23 // 線程狀態數組24 Thread.State[] threadStates = new Thread.State[10];25 26 // 設定線程的狀態27 for (int i = 0; i < 10; i++) {28 taskArr[i] = new Thread(new Pig());29 30 // 分別設定狀態31 if ((i % 3) == 0) {32 taskArr[i].setPriority(Thread.NORM_PRIORITY);33 } else if ((i % 3) == 1) {34 taskArr[i].setPriority(Thread.MIN_PRIORITY);35 } else if ((i % 3) == 2) {36 taskArr[i].setPriority(Thread.MAX_PRIORITY);37 }38 }39 40 // 將線程資訊寫入到檔案中便於分析41 FileWriter fWriter = new FileWriter(".\\log.txt");42 PrintWriter pWriter = new PrintWriter(fWriter);43 44 // 迴圈遍曆擷取線程的資訊45 for (int i = 0; i < 10; i++) {46 pWriter.println("線程 " + i + " 狀態:" + taskArr[i].getState());47 48 // 將當前線程狀態儲存到狀態數組中49 threadStates[i] = taskArr[i].getState();50 }51 52 // 啟動線程53 for (int i = 0; i < 10; i++) {54 taskArr[i].start();55 }56 57 // 在運行過程中如果線程的狀態和初始狀態不一樣就將狀態變化過程寫入到檔案中58 boolean finish = false;59 60 while (!finish) {61 for (int i = 0; i < 10; i++) {62 // 線程狀態發生變化63 if (taskArr[i].getState() != threadStates[i]) {64 // 列印線程當前資訊65 printThreadMsg(pWriter, taskArr[i], threadStates[i]);66 67 // 將當前線程狀態儲存到線程狀態數組中68 threadStates[i] = taskArr[i].getState();69 }70 }71 finish = true;72 for (int i = 0; i < 10; i++) {73 finish = finish && (taskArr[i].getState() == State.TERMINATED);74 }75 }76 }77 78 /**79 * 列印當前線程的資訊80 * @param pWriter81 * @param thread82 * @param state83 */84 private static void printThreadMsg(PrintWriter pWriter, Thread thread, State state) {85 pWriter.println("*********************************************************");86 pWriter.println("線程ID: " + thread.getId() + " 線程名稱:" + thread.getName());87 pWriter.println("線程優先順序:" + thread.getPriority());88 pWriter.println("線程過去狀態:" + state);89 pWriter.println("線程目前狀態:" + thread.getState());90 pWriter.println("*********************************************************");91 }92 }
部分執行結果如下:
分析上面的部分執行結果就可以看出當Pig線程進行休眠的時候,就會導致其他線程狀態的變換,其中過去狀態和目前狀態可以明顯的反應出線程狀態切換。
[Java並發編程]-線程的六種狀態及其狀態轉換