線程的主要有五種狀態
1.新建狀態:新創建了一個線程對象。
2.就緒狀態:線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。
3.運行狀態:就緒狀態的線程獲取了CPU,執行程序代碼。
4.阻塞狀態:阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。
5.掛起狀態:一般是指被掛起,因為同一時刻,需要“同步”運行的線程不止他一個,所以基於時間片輪轉的原則,他在獨占了一段時間的CPU後,被掛起,線程環境被壓棧。
下面就掛起和阻塞進行以下說明:
1.掛起是一種主動行為,因此恢復也應該要主動完成,而阻塞則是一種被動行為,是在等待事件或資源時任務的表現,你不知道他什麼時候被阻塞(pend),也就不能確切 的知道他什麼時候恢復阻塞。而且掛起隊列在操作系統裡可以看成一個,而阻塞隊列則是不同的事件或資源如信號量)就有自己的隊列。
2.阻塞pend)就是任務釋放CPU,其他任務可以運行,一般在等待某種資源或信號量的時候出現。掛起suspend)不釋放CPU,如果任務優先級高就永遠輪不到其他任務運行,一般掛起用於程序調試中的條件中斷,當出現某個條件的情況下掛起,然後進行單步調試。
3.pend是task主動去等一個事件,或消息.suspend是直接懸掛task,以後這個task和你沒任何關系,任何task間的通信或者同步都和這個suspended task沒任何關系了,除非你resume task;
4.任務調度是操作系統來實現的,任務調度時,直接忽略掛起狀態的任務,但是會顧及處於pend下的任務,當pend下的任務等待的資源就緒後,就可以轉為ready了。ready只需要等待CPU時間,當然,任務調度也占用開銷,但是不大,可以忽略。可以這樣理解,只要是掛起狀態,操作系統就不在管理這個任務了。
5.掛起是主動的,一般需要用掛起函數進行操作,若沒有resume的動作,則此任務一直不會ready。而阻塞是因為資源被其他任務搶占而處於休眠態。兩者的表現方式都是從就緒態裡“清掉”,即對應標志位清零,只不過實現方式不一樣。
這些術語是針對線程或進程來說的,比如有種叫法“進程三態”什麼的,但是不同的操作系統,或者同種操作系統不同版本見也存在狀態管理方式上的不同,比如還有什麼“進程五態”、“進程七態”的,我們可以把操作系統對進程的控制形象地比作雇人打工。
1、睡眠態:雇主對雇工說:“你睡覺去吧,某時某刻回來報道,接著干活!”
2、掛起態:雇主對雇工說:“你睡覺去吧,用得著你的時候,我會去叫你的,接著干活!”
3、就緒態:雇工的掃帚指CPU)被別的雇工搶了,自己只能按照規定的方式參與競爭比如Linux中是按時間片輪轉的方式),搶到就是自己的,然後接著干活!
4、阻塞態:雇工的抹布指非CPU的其他資源)被別的雇工搶了,自己只能干等著,等到了抹布,就進入就緒態,繼續參與到搶掃帚的競賽中。
這裡可以想象,睡眠和掛起應該是差不多的,睡眠應該是掛起多長時間後回來,但是他們都是一直占著CPU的。
WINDOWS不是實時操作系統,是搶占式的多線程操作系統,系統可以在任何時候停止一個線程調用另外的線程。
一個線程可以被掛起多次,SuspendThread多少次就要ResumeThread多少次,除了被別人調用SuspendThread掛起外,線程也可以告訴系統在一段時間內,可以將自己掛起,不需要調度。這可以調用Sleep實現。
void Sleep(DWORD dwMilliseconds);
這裡參數是表示線程要掛起多長時間,但是WINDOWS不是實時操作系統,不能保證到時候准時醒來,當為其傳入0時,表示主調線程主動放棄本次時間片的剩余部分。注意是本次。
當計算線程執行某任務所需的時間的時候,很多人習慣使用GetTickCount64
ULONG start=GetTickCount64(); //do something. ULONG end=GetTickCount64();
這個函數可能會由於線程中途被掛起而變得不准確,Windows提供了一個函數可以返回一個線程以獲得cpu時間
BOOL GetThreadTime( HANDLE hThread, PFILETIME pftCreationTime, PFILETIME pftExitTime, PFILETIME pftKernelTime, PFILETIME pftUserTime);
第一個參數為想獲得的線程句柄。
第二個參數返回線程創建時間-1601年1月1日0:00)的秒數。單位是100ns。
第三個表示退出時間-1601年1月1日0:00的秒數。單位是100ns。
第四個表示線程執行內核模式下的時間的絕對值。單位是100ns。
第五個表示線程執行用戶模式代碼的時間的絕對值。單位是100ns。
類似的,GetProcessTime可以返回進程中所有線程的時間之和。
在進行高精度的計算時上述函數仍然不夠。此時windows提供了以下函數:
BOOL QueryPerformanceFrequency(LARGE_INTEGER *pliFrequency) BOOL QueryPerformanceCounter(LARGE_INTEGER *pliCount);
這兩個函數假設正在執行的線程不會被搶占。它們都是針對生命期很短的代碼塊。GetCPUFrequencyInMHZ可以獲得cpu頻率。
本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1300631