多進程與多線程的本質區別在於:每一個進程擁有本身的一整套變量,而線程則共享數據。若是須要執行一個比較耗時的任務,應該使用獨立的線程。java
能夠經過實現Runnable
接口或繼承Thread
類來建立獨立的線程。多線程
1) 實現Ruannable
接口測試
class MyRunnable implements Runnable { public void run() { task code } } Ruannable r = new MyRuannable(); Thread t = new Thread(r); t.start();
2) 繼承Thread
類ui
class MyThread extends Thread { public void run() { task code } } Thread t = new MyThread(); t.start();
對於Thread
類或Runnable
對象,啓動新線程調用的是start()
方法,直接調用run()
方法只會在同一個線程中執行任務。start()
會啓動這個線程,引起調用run()
方法。start()
方法會當即返回,而且新線程並行運行。操作系統
若是有不少任務,爲每一個任務建立一個獨立的線程付出的代價太大,可使用線程池來解決這個問題。線程
當線程的run()
方法方法體執行完畢(天然終止)或在方法中出現沒有捕獲的異常時(意外終止),線程將終止。另外,可使用interrupt()
方法發送中斷請求強制線程終止。日誌
每一個線程都有boolean
標誌的中斷狀態位,想弄清當前線程是否被中斷(中斷狀態位是否被置位),須要當前線程本身判斷。而且,被中斷的線程能夠決定如何響應中斷。若是被中斷線程被阻塞,就沒法檢測中斷狀態,就會產生InterruptedException
異常。code
public void run() { try { do some work while(! Thread.currentThread().isInterrupted() && more work to do) { do more work } } catch(InterruptedException e) { // thread was interrupted during sleep or wait (in blocked) } finally { cleanup if required } }
當產生異常時,有兩種處理方式選擇。對象
1) 在catch
子句中設置中斷狀態。繼承
catch(InterruptedException e) { Thread.currentThread().interrupt(); }
2) 不採用try
語句塊捕獲異常,交給調用者處理。
void mySubTask() throws InterruptedException {}
測試當前線程是否被中斷有interrupted()
和isInterrupted()
兩個方法。interrupted()
是一個靜態方法,有反作用,會把中斷狀態位置爲false
;isInterrupted()
是一個實例方法,無反作用。
線程有6種狀態,能夠調用getState()
獲取線程狀態。
New:新建立狀態,在可運行前還有些工做要作;
Runnable:可運行狀態,可能正在運行也可能沒有運行,是否運行需看操做系統調度;
Blocked:被阻塞狀態,不活動,可能因爲請求鎖失敗;
Waiting:等待狀態,不活動,等待通知,好比調用Thread.join()
方法;
Timed Waiting:計時等待狀態,不活動,等待超時或通知,好比調用Thread.sleep(long millis)
或join(long millis)
方法;
Terminated:被終止狀態,線程可能因爲天然死亡或意外死亡。
每個線程都有一個優先級,默認繼承父線程。注意,不要將程序功能的正確性依賴於優先級。能夠經過setPriority(int newPriority)
方法設置線程優先級,最小優先級MIN_PRIORITY
爲1,默認優先級NORM_PRIORITY
爲5,最高優先級MAX_PRIORITY
爲10。
當操做系統的線程調度器有機會選擇新線程時,會首先選擇擁有較高優先級的線程。調用Thread
類的靜態方法yield()
可以使當前執行線程處於讓步狀態,若是有可運行的線程優先級大於等於此線程,那麼這些線程將被調度。
守護線程的惟一用途是爲其餘線程提供服務,經過調用t.setDaemon(true)
將線程轉化爲守護線程。若是隻剩下守護線程,虛擬機就會退出。
注意,守護線程應該永遠不去訪問固有資源,由於這些操做可能會發生中斷。
線程的run()
方法不能拋出任何被檢測的異常,但可能會拋出不被檢測的異常,致使線程終止。就在線程死亡以前,異常被傳遞到未捕獲異常處理器,進行處理,好比使用日誌API發送異常到日誌文件。
class MyUncaughtExceptionHandler implements UncaughtExceptionHandler { void uncaughtException(Thread t, Throwable e) { // t - terminated thread without exception catch // e - uncaught exception object do something like send exception info to log file } }
爲線程設置處理器可經過方法setUncaughtExceptionHandler()
或靜態方法setDefaultUncaughtExceptionHandler()
完成。若是不設置未捕獲異常處理器,那麼默認處理器爲空。
方法getUncaughtExceptionHandler()
用於獲取未捕獲異常處理器,可是有反作用,若是返回值爲空,那麼就會將ThreadGroup
對象設置爲處理器。線程組ThreadGroup
對象的執行流大體以下:
if(該線程組有父線程組) { 父線程組的uncaughtException方法被調用 } else { if(Thread.getDefaultExceptionHandler()返回非空處理器) { 調用該處理器 } else { if(Throwable是ThreadDeath的一個實例) { // 由過期方法stop產生 什麼都不作 } else { 輸出棧蹤影到標準錯誤流 } } }