- 執行緒(Thread)
- 一個OS有多個process在執行,稱為多工(multiprocessing/multitasking),屬於OS所控制
- 一個process可以有多個thread執行(一個程式執行多個動作),屬於program所控制,但OS也要支援
- 一般程式的main() 也是一個thread稱為main thread,main() method可以直接或間接產生許多的threads並同時執行,這就是所謂的multithreading多執行緒
- Timer與TimerTask這2個class就是應用Thread來實作
- java.lang 有關執行緒的class與interface
- Thread (implements Runnable)
- run(),currentThread(),getName(),start(),Thread(),Thread(Runnable),join(),sleep()
- Runnable
- public void run(); //只有一個run方法且為public
- Thread (implements Runnable)
public class j93110401
{
public static void main ( String[] args )
{
Thread thisThread = Thread.currentThread();
System.out.println( "thisThread.getName()="+thisThread.getName() ) ;
}
}
建立執行緒(Creations of Threads)
- 配合currentThread()與getName()可以在同一個class內建立多個執行緒
- 建立執行緒有兩種方式
1.繼承 Thread class
- 自定class繼承自Thread
- 自定class中 override Thread的run() method
- 在run()內可以有while(.T.)
- 建構自定的class實體
- 呼叫實體的start()方法,就會產生一個執行緒 //只能呼叫一次start()
2.實作 Runnable (implementing Runnable interface)
由於java並不允許多重繼承,因此若不是Thread類別的子類別,都要以此方法來建立執行緒
- 自定class implements Runnable
- 實作Runnable的run()
- 在run()內可有while(.T.)
- 建構一Thread的物件實體(必須將自定class的實體傳入Thread物件的建構函數)
- Thread th2 = new Thread (自定的class物件)
- 執行Thread物件實體.start()
控制執行緒(Controlling Threads)
- 當一個thread被new出來後,必須執行start()之後,才會進入runnable(排隊)狀態
- thread何時自runnable(排隊)變到running(存活)或由running變到runnable是由JVM的thread scheduler決定(JVM的分時多工處理)
- 程式設計師可以呼叫yield method使thread由running變到runnable
- 若thread遇到下列狀況,會由running變到blocked state
- 呼叫sleep method
- 呼叫wait method
- 呼叫join method
- 遇到I/O裝置 blocked
- 進入synchronized block時其lock被其他thread取走
- 當thread的block 狀態解除後, thread會回到runnable狀態,而非running狀態
- boolean isAlive() method可用來測試一個thread是否是 running的,因為一個thread的run()結束時,thread就死了,且不能restart。
yield與sleep與wait
- yield指的是參與排隊但交出控制權(running -> runnable)
- sleep指的是不參與排隊,休息指定的秒數後才繼續參與排隊(running->blocked->runnable)
- wait指的是不參與排隊,等待其他執行緒notify或notifyall後才繼續參與排隊,但注意wait要在一個迴圈中才能再參與排隊(running->blocked->runnable)
wait()、notify() 和 notifyAll() 方法
- 因為使用輪詢(poll ,它可能消耗大量 CPU 資源,而且具有計時不精確的特性),Object 類別包括了一些方法,可以讓執行緒相互通知事件的發生如notify(),notifyall(),wait()。
- Object 類別定義了 wait()、notify() 和 notifyAll() 方法。要執行這些方法,必須擁有相關物件的鎖。
- Wait() 會讓呼叫執行緒休眠,直到用 Thread.interrupt() 中斷它、過了指定的時間、或者另一個執行緒用 notify() 或notifyAll() 喚醒它。
- 當對某個物件呼叫 notify() 時,如果有任何執行緒正在透過 wait() 等待該物件,那麼就會喚醒其中一個執行緒。當對某個物件呼叫 notifyAll()時,會喚醒所有正在等待該物件的執行緒。
- 這些方法是更複雜的鎖定、佇列和concurrency程式碼的元件。但是,notify() 和 notifyAll() 的使用很複雜。尤其是,使用notify() 來代替 notifyAll() 是有風險的。除非您確實知道正在做什麼,否則就使用 notifyAll()。
- 與其使用 wait() 和 notify() 來編寫您自己的排程程式、執行緒池、佇列和鎖,倒不如使用 util.concurrent package,這是一個被廣泛使用的開放源碼toolkit,裡面都是有用的concurrency實用程式。JDK1.5 將包括 java.util.concurrent package;它的許多類別都衍生自 util.concurrent。
加入(join)執行緒
- Thread API 包括等待另一個執行緒完成的方法︰join()。當呼叫 Thread.join() 時,呼叫執行緒將阻斷,直到目標執行緒完成為止。
- Thread.join() 通常由使用執行緒的程式使用,以將大問題劃分成許多小問題,每個小問題指派一個執行緒。本章末的範例建立十個執行緒,啟動它們,然後使用Thread.join() 等待它們全部完成。