併發編程線程基礎(一)

併發編程線程基礎(一)

1.1 什麼是線程

這種老生常談的問題在這裏簡單說一下啊,線程是操作系統調度的最小單元,也叫作輕量級進程。	在一個進程中可以創建多個線程
,這些線程都應有各自的計數器、堆棧和局部變量等屬性,並且都能夠訪問共享的內存變量。

1.2 線程的狀態

	1. New ,新創建狀態。線程被創建,還沒有調用start方法,在線程運行之前還有一些基礎工作要做。
	2. Runnable,可運行狀態。一旦調用start方法,線程線程就處於Runnable狀態。一個可運行的線程可能正在運行也節能沒有運行,這取決於操作系統給線程提供運行的時間。
	3. Blocked,阻塞狀態。表示線程被鎖阻塞,他暫時不活動。
	4. Waiting,等待狀態。線程暫時不活動,並且不運行任何代碼,這消耗最少的資源,直到線程調度器重新激活它。
	5. Time waiting,超市等待狀態。和等待狀態不同的是,它是可以在指定的時間自行返回的。
	6. Terminated,終止狀態。表示當前線程已經執行完畢。導致線程終止有兩種情況:第一種就是run方法執行完畢正常退出;第二種就是因爲一個沒有捕獲的異常而終止了run方法,導致線程進入終止狀態。

1.3 線程的創建與運行

線程創建有三種方法
	1. 繼承Thread類,重寫run方法
	2. 實現Runnable接口,並實現該接口的run方法
	3. 實現Callable接口,重寫call方法 

1.4 線程的通知與等待

1.4.1 wait()函數
	當一個線程調用一個共享變量的wait()方法時,該調用線程被阻塞掛起直到發生下面幾件事情之一才返回:(1)其他線程調用了該共享變量的notify()或者notifyAll()方法;
	(2)其他線程調用了該線程的interrupt()方法,該線程拋出InterruptException異常返回還有一個需要注意的是如果調用wait()方法的線程沒有
	事先獲取該對象的監視器鎖,則調用wait()方法時調用線程會拋出IllegalMonitorStateException異常。

1.4.2 wait(long timeout)函數
	如果一個線程調用共享對象的該方法掛起後,沒有在指定timeout ms 時間內被其他線程調用該共享變量的notify(),或者notifyAll()方法喚醒,那麼該函數還是會因爲超時而返回。

1.4.3 wait(long timeout,int nanos)函數
	在其內部調用的是wait(long timeout )函數。只有nanos>0時才使參數timeout 遞增1.

1.4.5 notify()函數
	一個線程調用共享對象的notify()方法後,會喚醒一個在該共享變量上調用wait系列方法後被掛起的線程。一個共享變量上可能會有多個線程在等待,具體喚醒哪個等待的線程是隨機的。
	
	被喚醒的線程不能馬上從wait方法返回並繼續執行,必須在獲取了共享對象的監視器鎖後纔可以返回。

1.4.6 notifyAll()函數
	不同於咋共享變量上調用notify()函數會喚醒被阻塞到該共享變量上的一個線程,notifyAll()方法則會喚醒所有在該共享變量上由於調用wait系列方法而被掛起的線程。

1.4 等待線程執行終止的join方法

join方法是Thread類提供的,可以等待多個線程全部執行完畢後再做處理。

1.5 讓線程睡眠的sleep方法

Thread類中有一個靜態的sleep方法,當一個執行中的線程調用了Thread的sleep方法後,調用線程會暫時讓出指定時間 的執行權,
也就是在這期間不參與CPU的調度,但是該線程所擁有的監視器資源,比如鎖還是持有不讓出的。
指定的睡眠時間到了後該函數會正常返回,線程就處於就緒狀態,然後參與ZPU的調度獲取到CPU的資源後就可以繼續運行了。
如果在睡眠期間其他線程調用了該線程的interropt方法中斷了該線程則該線程會在調用sleep方法的地方拋出InterruptedException異常而返回。

1.6 讓出CPU執行權的yield方法

當一個線程調用yield方法時,當前線程會讓出CPU使用權,然後處於就緒狀態,線程調度器會從就緒隊列裏面獲取一個線程優先級最高的線程,
當然也有可能會調度到剛剛讓出CPU的那個線程來獲取CPU執行權。

1.7 線程終斷

Java中的線程中斷是一種線程間的協作模式,通過設置線程的中斷標誌並不能直接終止該線程的執行,而是被中斷的線程根據中斷狀態自行處理。
void interrupt()方法:中斷線程。例如當線程A運行時,線程B可以調用A的interrupt方法來設置線程A的中斷標誌爲true並立即返回。
設置標誌僅僅是設置標誌,線程A實際並沒有被中斷,它會繼續往下執行。如果線程A因爲調用了wait系列函數 join方法或者sleep方法而被阻塞掛起這時候B線程調用線程A的interrupt方法,線程A會在調用這些方法的地方拋出InterruptedException異常而返回。

void isInterrupted()方法 
檢測當前線程是否被中斷,如果是返回true,否則返回false。

void interrupted()方法 
檢測當前線程是否被中斷,如果是返回true 否則返回false。與isInterrupted不同的是該方法如果發現當前線程被中斷,則會清楚中斷標誌,並且該方法是static方法,可通過Thread類直接調用。

1.8 理解線程上下文切換

多線程編程中線程個數一般都大於CPU個數,而每個CPU同一時刻只能被一個線程使用,爲了讓用戶感覺多個線程是在同時執行的,
CPU資源的分配採用了時間片輪轉的策略,也就是給每個線程分配一個時間片,線程在時間片內佔用CPU執行任務。當前線程使用完
時間片後,就會處於就緒狀態並讓出CPU讓其他線程佔用,這就是上下文切換,從當前線程的上下文切換到了其他線程。

線程上下文切換時機有 : 當前線程的CPU時間片使用完處於就緒狀態時,當前線程被其他線程中斷時。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章