標籤:區別 喚醒 sys 通過 sleep reads inter oid info
線程狀態及轉化
借用網上的一幅圖:
說明:
線程一共分為5種狀態
建立狀態(new)
線程對象被建立後,就進入了建立狀態,例如:Thread t = new Thread();
就緒狀態(Runnable)
線程對象被建立後,其它線程調用了該對象的start()方法,從而來啟動該線程。
例如,thread.start()。處於就緒狀態的線程,然後等待CPU調度執行。可不是run()方法-_-;
當如果多次調用start(),這時會報異常。
public synchronized void start() { //A zero status value corresponds to state "NEW". if (threadStatus != 0) throw new IllegalThreadStateException();
運行(Running)
線程擷取CPU許可權進行執行。需要注意的是,線程只能從就緒狀態進入到運行狀態。
堵塞(blocked)
阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。阻塞的情況分三種,狀態是兩種(blocked 和waiting):
- 等待阻塞 -- 通過調用線程的wait()方法,讓線程等待某工作的完成。
- 同步阻塞 -- 線程在擷取synchronized同步鎖失敗(因為鎖被其它線程所佔用),它會進入同步阻塞狀態。
- 其他阻塞 -- 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態逾時、join()等待線程終止或者逾時、或者I/O處理完畢時,線程重新轉入就緒狀態。
blocked 和waiting 區別,blocked是在臨界點外面等待進入,waiting是在臨界點裡面等待notify,當線程調用了join方法,jion了另外的線程的時候,也會進入waiting狀態,等待被它jion的線程結束。
死亡(Dead)
線程執行完了或者因異常退出了run()方法,該線程結束生命週期。
線程的建立
線程建立有3中方式:
1、繼承Thrad:
Thread t = new Thread(){ public vvoid run(){ System.out.println("new Thread"); };};
2、實現Runnable介面:
Thread t = new Thread(new Runnable(){ public void run(){ System.out.println("new Thread"); };});
3、使用Callable和Future建立線程
FutureTask<String> ft = new futureTask<String>(){ public String call() throws Exception{ System.out.println("new Thread"); return "abc"; }}Thread t = new Thread(ft);ft.start();String result= ft.get();
線程方法Object中方法
wait(),notify(),notifyAll()都是定義在Object類中,它們都是依賴於同步鎖,而同步鎖是對象鎖持有,並且每個對象只有一個!這就是為什麼notify(),wait()等函數定義在Object類,而不是Thread類中的原因。
注意:調用wait/notify/notifyAll一定是在擷取對象的鎖之後,否則會報錯哈!java.lang.IllegalMonitorStateException
wait()
方法是將當前線程進入等待(waiting)狀態,同時也會讓當前線程釋放它持有的鎖(同步鎖),直到其他線程調用此對象的notify()活notifyAll(),喚醒當前對象上的線程(單個或所有),讓其進入就緒狀態,等待cpu調度,才能繼續執行wait之後的代碼;
wait(long timeout)
也是讓當前的線程進入等待(TIMED_WAITING)狀態,該方法可以指定逾時時間,當調用此對象的notify()或者NotifyAll(),或者超過指定的時間,則線程也會別喚醒,進入就緒狀態;
wait(long timeout,int naous)
notify()和notifyAll()是喚醒當前對象上的等待線程,notify是喚醒單個線程,而notifyAll則是喚醒所有的線程;
整體流程是這樣:當一個線程擷取對象的同步鎖後,然後執行直到wait()方法,這時該線程進入等待狀態,釋放該對象的同步鎖,這時另外一個線程(喚醒線程)擷取同步鎖後(這裡的同步鎖一定是和等待線程的同步鎖是同一個),執行到notify()或notifyAll()後,才能喚醒等待線程,雖然等待線程被喚醒,但是它不能立刻執行,因為喚醒線程還持有該對象的同步鎖,必須等待喚醒線程釋放了對象的同步鎖之後,等待線程才能擷取對象的同步鎖進而繼續運行。
Thread中方法
yeild(),sleep()都是定義在Thread類中
yeild()
它的作用是讓步,也就是說由正在啟動並執行狀態進入到就緒狀態,從而讓其他具有相同優先順序的線程擷取執行權,但是,並不能保證在當前線程調用yeild方法後,其他線程一定能擷取執行權,也有可能是當前線程再次進入運行狀態繼續執行。
sleep()
讓當前線程休眠,即讓當前線程由運行狀態轉換到阻塞狀態,sleep可指定休眠時間,當線程的休眠時間超過了指定的時間,線程會被喚醒,由阻塞狀態變成就緒裝,然後等待cpu調度。
特別注意,sleep()是不會釋放對象的同步鎖,就是單純的讓線程阻塞。
interrupt()
當線程調用interrupt(),只是設定了線程的中斷狀態,並不會終止線程,剩下的是由你自己來處理該線程怎麼辦,wait(), wait(timeout), join(), sleep(timeout), await(),await(timeout)等方法都是可以被interrupt()方法中斷的。
線程釋放鎖一個是方法執行完、調用wait、代碼拋出異常。
java-線程-基礎