進程是程序的一次動態執行過程,是系統進行資源分配和調度運行的基本單位。
線程是進程的一個實體,它是比進程更小的的能夠獨立運行的基本單位。在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。線程基本自己不擁有系統資源,只擁有一點在運行中必不可少的資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統內多個程序間并發執行的程度。它可與同屬一個進程中的其他線程共享進程所擁有的全部資源。
2、引入線程與進程的目的在OS中引入進程的目的是為了使更多的程序能夠并發執行,以提高資源的利用率和系統的吞吐量。
引入線程的則是為了減少程序在并發執行時所付出的時間開銷,使OS具有更好的并發性,以進一步提高資源的利用率和系統的吞吐量。
3、程序、進程與線程的關系程序是保存在硬盤上的可執行代碼,是一種靜態的概念。
進程是一個程序在計算機上執行的過程,是一種動態的概念。
線程是進程的一部分,進程包含多個線程在運行。
形象的比喻:將計算機的CPU比作一座工廠,它承擔了所有的計算任務。
由于單個CPU一次只能運行一個任務,所以此工廠一次只能供給一個車間。進程好比是這個車間,任何一個時刻CPU總是運行一個進程,其他進程處于非運行狀態。
一個車間里有很多工人協同完成一個任務,線程好比車間里的工人,一個進程可以包括多個線程。
車間的空間是工人們共享的,這象征著一個進程的內存空間是共享的,每個其包括的線程可以使用這些共享內存。
可每間房間的大小不同,有些房間只能容納一個人,比如廁所,里面有人的時候,其他人就不能進入。這代表一個線程使用某些共享內存的時,其他線程必須等它結束,才能使用這一塊內存。
一個人防止他人進入的簡單方法就是在門口加一把鎖。先到的人鎖上門,后來的人看見上鎖就在門口排隊,等鎖打開在進入,這叫做“互斥鎖”(Mutual exclusion,縮寫 Mutex),防止多個線程同時讀取某一塊內存區。
具體比如: Word程序的源代碼就是保存在硬盤上的可執行代碼,是靜態的,當啟動Word程序時對于操作系統就相當于啟動了一個進程,而在這個進程還有許多功能(如拼寫檢查)是通過一個個線程實現的。如果Word關閉了,則這些拼寫檢查的線程也將消失,但是如果拼寫檢查的線程關閉了,也并不會讓Word的進程關閉。
4、任何線程一般具有5種狀態:創建、就緒、運行、阻塞、終止創建狀態:新建一個線程對象可采用Thread類的構造方法來實現。
就緒狀態:調用start()方法啟動線程,此時線程進入線程隊列排隊,等待CPU的服務。
運行狀態:調運線程對象的run()方法。
阻塞狀態:在可執行狀態下,如果調用sleep()、suspend()、wait()等方法,線程進入阻塞狀態
只有當引起阻塞狀態的原因消失時,線程才可以進入阻塞狀態。
死亡狀態:調用stop()方法或run()方法執行結束時。
5、Java中的多線程1.Java中的實現方式:
在Java中線要實現多線程操作有兩種常用的手段: 一種是繼承Thread類,另外一種是實現Runable接口。
通過繼承Thread類實現多線程必然受到單繼承的局限性的影響,所以一般來說,都是通過實現Runable接口來實現多繼承。
兩種方式都必須明確覆寫run()方法,此方法為線程的主體。
繼承Thread類要通過start()方法啟動線程,而Runable接口還是要依靠Thread類的start()方法來啟動線程。
2.Thread類與Runable接口的聯系與區別:
聯系:
1.Thread的類也是Runable接口的子類,但是Thread類中并沒有完全實現Runable接口中run()方法,所以兩種方式都必須明確覆寫run()方法。
2.二者的操作方式類似于代理模式:
Thread類與Runable接口的子類都同時實現了Runable接口,之后將Runable的子類放到Thread類的構造器中,調用Thread類的start()方法啟動線程。
區別:
1.啟動線程的方式不同
2.局限性不同
3.實現Runable接口的對象可以方便的實現資源的共享,而繼承Thread類則多個程序之間無法共享線程類的實例對象。
(原因:當繼承Thread類實現多線程時,程序每新建一個線程都需要創建一個Thread類對象,因此多個線程之間不能共享實例變量。 Runable對象僅僅作為Thread對象的target,Runable實現類的run()方法僅作為線程執行體,而實際的的線程對象依然是Thread的實例。多個線程可以共享一個target,所以一多個線程共享一個Runable對象的實例變量。)
3.為什么啟動線程時不能直接使用run()方法:
調用start()方法來啟動線程,系統會把該run()當成線程的執行體來處理;但如果直接調用線程對象的run()方法,則run()將會被當做一個普通方法被執行,而不是線程的執行體。
6、死鎖的概念7、進程同步在多道程序環境下,系統中各進程以不可預測的速度向前推進,進程的異步性對臨界資源的訪問會給系統造成混亂,造成了結果的不可再現性。為防止這種現象,引入進程同步的概念。
在操作系統中,進程是占有資源的最小單位(線程可以訪問其所在進程內的所有資源,但線程本身并不占有資源或僅僅占有一點必須資源)。但對于某些資源來說,其在同一時間只能被一個進程所占用。這些一次只能被一個進程所占用的資源就是所謂的臨界資源(例如現實生活中的廁所就是一個典型的臨界資源)。典型的臨界資源比如物理上的打印機,或是存在硬盤或內存中被多個進程所共享的一些變量和數據等(如果這類資源不被看成臨界資源加以保護,那么很有可能造成丟數據的問題)。
對于臨界資源的訪問,必須是互訴進行。也就是當臨界資源被占用時,另一個申請臨界資源的進程會被阻塞,直到其所申請的臨界資源被釋放。而進程內訪問臨界資源的代碼被成為臨界區。
解決同步問題的兩種方式:
同步代碼塊
synchronized(同步對象){ ... //需要同步的代碼; }同步方法
synchronized 關鍵字將一個方法聲明為同步方法。
//synchronized的音標['s??kr?na?zd]
對于臨界區的訪問過程分為四個部分:
1.進入區:查看臨界區是否可訪問,如果可以訪問,則轉到步驟二,否則進程會被阻塞
2.臨界區:在臨界區做操作
3.退出區:清除臨界區被占用的標志
4.剩余區:進程與臨界區不相關部分的代碼
8、線程池引入原因:
系統啟動一個新的線程的成本比較高,因為它涉及與操作系統交互。在這種情況下,使用線程池可以很好的提高性能。尤其是當程序中需要創建大量的生存期很短暫的線程時,更應該考慮使用線程池。
實現過程:
線程池在系統啟動時即創建大量空閑的線程,程序將一個Runable對象傳給線程池,線程池就會啟動一個線程來執行run()方法,當run()方法結束后,該線程并不會死亡,而是再次回到線程池中成為空閑狀態,等待下一個Runable對象的run()方法。
其他優勢:
線程池還可以有效的控制系統中并發進程的數量,通過設置線程池的最大線程數參數可以控制系統中并發線程數不超過此數,避免系統中包含大量并發線程導致JVM崩潰。
新聞熱點
疑難解答