線程
線程是一個程序內部的順序控制流。線程是一個程序里面不同的執行路徑
通常在一個進程中可以包含若干個線程,當然一個進程中至少有一個線程,不然沒有存在的意義。線程可以利用進程所擁有的資源,在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位,由于線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統多個程序間并發執行的程度。
進程(process)
狹義定義:進程就是一段程序的執行過程。
廣義定義:進程是一個具有一定獨立功能的程序關于某個數據集合的一次運行活動。它是操作系統動態執行的基本單元,在傳統的操作系統中,進程既是基本的分配單元,也是基本的執行單元。
簡單的來講進程的概念主要有兩點:第一,進程是一個實體。每一個進程都有它自己的地址空間,一般情況下,包括文本區域(text region)、數據區域(data region)和堆棧(stack region)。文本區域存儲處理器執行的代碼;數據區域存儲變量和進程執行期間使用的動態分配的內存;堆棧區域存儲著活動過程調用的指令和本地變量。第二,進程是一個“執行中的程序”。程序是一個沒有生命的實體,只有處理器賦予程序生命時,它才能成為一個活動的實體,我們稱其為進程。
進程狀態:進程有三個狀態,就緒、運行和阻塞。就緒狀態其實就是獲取了出cpu外的所有資源,只要處理器分配資源就可以馬上執行。就緒狀態有排隊序列什么的,排隊原則不再贅述。運行態就是獲得了處理器分配的資源,程序開始執行。阻塞態,當程序條件不夠時候,需要等待條件滿足時候才能執行,如等待i/o操作時候,此刻的狀態就叫阻塞態
多線程
在一個程序中,這些獨立運行的程序片段叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理”。多線程是為了同步完成多項任務,不是為了提高運行效率,而是為了提高資源使用效率來提高系統的效率。線程是在同一時間需要完成多項任務的時候實現的。
最簡單的比喻多線程就像火車的每一節車廂,而進程則是火車。車廂離開火車是無法跑動的,同理火車也不可能只有一節車廂。多線程的出現就是為了提高效率。
線程和進程的區別:
定義方面:進程是程序在某個數據集合上的一次運行活動;線程是進程中的一個執行路徑。(進程可以創建多個線程)
角色方面:在支持線程機制的系統中,進程是系統資源分配的單位,線程是CPU調度的單位。
資源共享方面:進程之間不能共享資源,而線程共享所在進程的地址空間和其它資源。同時線程還有自己的棧和棧指針,程序計數器等寄存器。
獨立性方面:進程有自己獨立的地址空間,而線程沒有,線程必須依賴于進程而存在。
開銷方面。進程切換的開銷較大。線程相對較小。(前面也提到過,引入線程也出于了開銷的考慮。)
(1)進程是資源的分配和調度的一個獨立單元,而線程是CPU調度的基本單元
? ?? ?????(2)同一個進程中可以包括多個線程,并且線程共享整個進程的資源(寄存器、堆棧、上下文),一個進行至少包括一個線程。
? ? ? ? ? (3)進程的創建調用fork或者vfork,而線程的創建調用pthread_create,進程結束后它擁有的所有線程都將銷毀,而線程的結束不會影響同個進程中的其他線程的結束
? ? ? ? ? (4)線程是輕兩級的進程,它的創建和銷毀所需要的時間比進程小很多,所有操作系統中的執行功能都是創建線程去完成的
? ? ? ? ? (5)線程中執行時一般都要進行同步和互斥,因為他們共享同一進程的所有資源
? ? ? ? ? (6)線程有自己的私有屬性TCB,線程id,寄存器、硬件上下文,而進程也有自己的私有屬性進程控制塊PCB,這些私有屬性是不被共享的,用來標示一個進程或一個線程的標志
進程:進程是一個靜態的概念
線程:一個進程里面有一個主線程叫main()方法,是一個程序里面的,一個進程里面不同的執行路徑。
在同一個時間點上,一個CPU只能支持一個線程在執行。因為CPU運行的速度很快,因此我們看起來的感覺就像是多線程一樣。
進程與線程的選擇取決以下幾點:
1、需要頻繁創建銷毀的優先使用線程;因為對進程來說創建和銷毀一個進程代價是很大的。2、線程的切換速度快,所以在需要大量計算,切換頻繁時用線程,還有耗時的操作使用線程可提高應用程序的響應3、因為對CPU系統的效率使用上線程更占優,所以可能要發展到多機分布的用進程,多核分布用線程;4、并行操作時使用線程,如C/S架構的服務器端并發線程響應用戶的請求;5、需要更穩定安全時,適合選擇進程;需要速度時,選擇線程更好。
在java.lang.Thread類中,提供了sleep(),
而java.lang.Object類中提供了wait(), notify()和notifyAll()方法來操作線程
sleep()可以將一個線程睡眠,參數可以指定一個時間。
而wait()可以將一個線程掛起,直到超時或者該線程被喚醒。
??? wait有兩種形式wait()和wait(milliseconds).
sleep和wait的區別有:
? 1,這兩個方法來自不同的類分別是Thread和Object
? 2,最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其他線程可以使用同步控制塊或者方法。
? 3,wait,notify和notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在
??? 任何地方使用
?? synchronized(x){
????? x.notify()
???? //或者wait()
?? }
?? 4,sleep必須捕獲異常,而wait,notify和notifyAll不需要捕獲異常
使用實現Runnable接口和繼承Thread類這兩種開辟新線程的方法的選擇應該優先選擇實現Runnable接口這種方式去開辟一個新的線程。因為接口的實現可以實現多個,而類的繼承只能是單繼承。因此在開辟新線程時能夠使用Runnable接口就盡量不要使用從Thread類繼承的方式來開辟新的線程。