Java中的線程

進程和線程:

	進程:是指一個內存中運行的應用程序,每個進程都有自己獨立的一塊內存空間,一個進程中可以有多個線程。比如在Windows系統中,一個運行的xx.exe就是一個進程。
		Java程序的進程中有幾個線程:主線程、垃圾回收線程

	線程:是指進程中的一個執行任務,一個進程中可以運行多個線程,多個線程可共享數據

	進程與線程的區別:
		1)進程有獨立的進程空間,進程中的數據存放空間(堆空間和棧空間)是獨立的。
		2)線程的堆空間是共享的,棧空間是獨立的,線程消耗的資源也比進程小,相互之間可以影響的。

	線程的生命週期:
		1)新建(New):當程序創建了一個線程後,該線程處於新建狀態。
		2)就緒(Ready):當線程對象調用啓動方法後,該線程處於就緒狀態,線程計入線程隊列排隊,此時該狀態線程並未開始執行,它僅表示可以運行了
		3)運行(Running):若處於就緒狀態的線程獲得了CPU,開始執行run()線程執行體,該線程處於執行狀態
		4)阻塞(Blocked):線程運行過程中需要被中斷
			注意:阻塞狀態不能直接轉成運行狀態,阻塞狀態只能重新進入就緒狀態
			線程阻塞的原因:
				1>線程(調用sleep方法或wait方法)主動放棄佔用的CPU資源。
				2>線程調用了阻塞式的IO方法,在該方法返回前,線程被阻塞。
				3>線程訪問臨界資源時,沒有獲取到相關的鎖。
				4>線程被掛起。
		5)死亡(Terminated):
			1>線程正常結束。
			2>線程拋出未捕獲的Exception或Error
	
		
java中的線程:

	創建線程三種方式:
	
		1)繼承Thread類:
			1>子類重寫父類中的run方法。
			2>建立子類對象的同時線程也被創建。
			3>通過調用start方法啓動線程:new MyThread().start();
			
			特點:不能再繼承其他類了,同份資源不共享。
			
			注意:Thread類實現了Runnable接口
		
		2)實現Runnable接口:
			1>子類覆蓋接口中的run方法。
			2>通過Thread類創建線程,並將實現了Runnable接口的子類對象作爲參數傳遞給Thread類的構造函數。
			3>Thread類對象調用start方法啓動線程:
				new Thread(new Runnable(){
					public void run() {
						...
					}
				}).start();
				
			特點:
				1>多個線程共享一個目標資源(即run方法中的內容),適合多線程處理同一份資源。
				2>該類還可以繼承其他類,也可以實現其他接口,擴展性較好。
			
		3)實現Callable接口(jdk1.5):
		
			java.util.concurrent包下的Callable接口:
				
				public interface Callable<V> {
					V call() throws Exception;
				}

			Callable和Runnable的區別:
				1)Callable定義的方法是call,而Runnable定義的方法是run。
				2)Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。
				3)Callable的call方法可拋出異常,而Runnable的run方法不能拋出異常。
			
			
	線程的狀態(生命週期):
	
		java.lang.Thread.State
	
		public enum State {
			// Thread state for a thread which has not yet started.
			NEW, // 新建狀態

			/**
			 * Thread state for a runnable thread.  
			 * A thread in the runnable state is executing in the Java virtual machine but it may
			 * be waiting for other resources from the operating system such as processor.
			 * java將操作系統中運行和就緒兩個狀態合併稱爲運行狀態。我們也可以細分一下:
			 * 		就緒狀態:當線程對象調用start()方法後,該線程處於就緒狀態,線程計入線程隊列排隊,此時該線程並未開始執行,它僅表示線程已經準備就緒。
			 * 		運行狀態:若處於就緒狀態的線程獲得了CPU,開始執行run()線程執行體,此時該線程處於運行狀態。
			 */
			RUNNABLE, // 運行狀態

			/**
			 * Thread state for a thread blocked waiting for a monitor lock.
			 * A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or reenter a synchronized block/method after calling {Object.wait}.
			 * 線程在訪問synchronized修飾的方法或方法塊時,因無法獲得監視器而進入阻塞狀態。或者是線程進入同步方法(同步代碼塊)後調用了Object.wait()方法。
			 * 
			 * 線程調用了阻塞式的IO方法,在該方法返回前,線程被阻塞。
			 */
			BLOCKED, // 阻塞狀態

			/**
			 * Thread state for a waiting thread.
			 * A thread is in the waiting state due to calling one of the following methods:
			 *****  {Object.wait} with no timeout *****
			 *****  {Thread.join} with no timeout *****
			 *****  {LockSupport.park}			  *****
			 *
			 * A thread in the waiting state is waiting for another thread to perform a particular action.
			 *
			 * For example, a thread that has called Object.wait() on an object is waiting for another thread to call Object.notify() or Object.notifyAll() on that object.
			 * A thread that has called Thread.join() is waiting for a specified thread to terminate.
			 * 
			 * 注意:線程因無法獲取到java.util.concurrent.locks.lock鎖,進入等待狀態,而不是進入阻塞狀態!因爲lock是使用LockSupport的park()方法來實現線程的阻塞。
			 */
			WAITING, // 等待狀態

			/**
			 * Thread state for a waiting thread with a specified waiting time.
			 * A thread is in the timed waiting state due to calling one of the following methods with a specified positive waiting time:
			 *   {Thread.sleep}
			 *   {Object.wait} with timeout
			 *   {Thread.join} with timeout
			 *   {LockSupport.parkNanos}
			 *   {LockSupport.parkUntil}
			 */
			TIMED_WAITING, // 超時等待狀態

			/**
			 * Thread state for a terminated thread.
			 * 	進入死亡狀態的場景:
			 * 		1)run()執行完成,線程正常結束
			 * 		2)線程拋出未捕獲的Exception或Error
			 * 		3)調用線程的stop() (易導致死鎖,不推薦)
			 *	注意:
			 *		1)主線程結束後,其他線程不受其影響,不會隨之結束;一旦子線程啓動起來後,就擁有和主線程相等地位,不受主線程影響。
			 *		2)測試線程是否活着,可用線程對象的isAlive()方法。
			 * 		3)已死亡的線程是不可能通過start()方法喚醒線程的(線程死不能復生),否則引發IllegalThreadStateException異常
			 */
			TERMINATED; // 死亡狀態(或結束狀態)
		}
		


	線程的優先級:
	
		1)每個線程都有優先級,優先級的高低只和線程獲得執行機會的次數多少有關,並非線程優先級越高的就一定先執行,哪個線程的先運行取決於CPU的調度;
		2)線程優先級的繼承性:如果A線程啓動B線程,則B線程的優先級與A線程是一樣的。
			eg:默認情況下main線程具有普通的優先級,而它創建的線程也具有普通優先級。
		3)Thread對象的setPriority(int x)和getPriority()來設置和獲得優先級。
			MAX_PRIORITY	:	值是10
			MIN_PRIORITY	:	值是1
			NORM_PRIORITY	:	值是5(主方法默認優先級)

		注意:不能在程序中通過Java線程的優先級來判斷都處於就緒狀態的線程的執行順序。
			1>Java的線程是通過映射到操作系統的原生線程上來實現的,故最終的調度還是取決於操作系統。
			2>雖然操作系統也提供線程優先級的功能,但是並不能和Java線程的優先級一一對應,Java線程的優先級可能被操作系統改變。
			
	
	守護線程:
	
		說明:當進程中不存在非守護線程時,守護線程會自動銷燬。
			

線程安全:

	概念:在多線程環境下,一個類在執行某個方法時,對類的實例變量的訪問是安全的(保證原子性+可見性),也就是我們所說的多線程的同步訪問。

	
避免死鎖:
	1)避免一個線程同時獲取多個鎖
	2)嘗試使用定時鎖,使用lock.tryLock(timeout)。
	3)使用枚舉:枚舉類的構造函數爲私有,不能再創建枚舉對象,枚舉對象的聲明和初始化都是在static塊中,故保證了枚舉類的線程安全。
	
	
	
	
	
	

發佈了298 篇原創文章 · 獲贊 56 · 訪問量 34萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章