第 10 章 java 的執行緒 10-1 執行緒的基礎 10-2 java 執行緒的使用方法 10-3 java...

22
10 10 Java Java 第第第第 第第第第 10-1 10-1 第第第第第第 第第第第第第 10-2 Java 10-2 Java 第第第第第第第第 第第第第第第第第 10-3 Java 10-3 Java 第第第第第第 第第第第第第 10-4 10-4 第第第第第第第第 第第第第第第第第

Post on 18-Dec-2015

270 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

第第 1010 章 章 JavaJava 的執行緒的執行緒

10-1 10-1 執行緒的基礎執行緒的基礎10-2 Java10-2 Java 執行緒的使用方法執行緒的使用方法10-3 Java10-3 Java 執行緒的同步執行緒的同步10-4 10-4 管道串流的執行緒管道串流的執行緒

Page 2: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-1 10-1 執行緒的基礎執行緒的基礎

10-1-1 Java10-1-1 Java 的執行緒的執行緒10-1-2 10-1-2 多工與多執行緒多工與多執行緒

Page 3: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-1-1 Java10-1-1 Java 的執行緒的執行緒 -- 說明說明

「執行緒」(「執行緒」( ThreadThread ))也稱為「輕量行程」也稱為「輕量行程」(( Lightweight ProcesLightweight Processs ),其執行過程類似上),其執行過程類似上述程式執行,只是執行述程式執行,只是執行緒不能單獨存在或執行,緒不能單獨存在或執行,一定需要隸屬於一個程一定需要隸屬於一個程式,由程式啟動執行緒,式,由程式啟動執行緒,如右圖所示:如右圖所示:

Page 4: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-1-1 Java10-1-1 Java 的執行緒的執行緒 -- 多執行緒多執行緒

如果程式碼本身沒有先如果程式碼本身沒有先後依存關係,程式能夠後依存關係,程式能夠分割成多個同步執行緒分割成多個同步執行緒來一起執行,這種程式來一起執行,這種程式設計方法稱為「平行程設計方法稱為「平行程式設計」(式設計」( Parallel Parallel ProgrammingProgramming ),如右),如右圖所示:圖所示:

Page 5: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-1-2 10-1-2 多工與多執行緒多工與多執行緒

目前的作業系統都強調「多工」目前的作業系統都強調「多工」(( MultitaskingMultitasking )。例如:微軟的)。例如:微軟的WindowsWindows 作業系統屬於一套多工的作業系作業系統屬於一套多工的作業系統,可以同時執行小畫家、記事本和小算統,可以同時執行小畫家、記事本和小算盤等多個應用程式。盤等多個應用程式。不同於作業系統的多工,「多執行緒」不同於作業系統的多工,「多執行緒」(( MultithreadedMultithreaded )是指在單一應用程式擁)是指在單一應用程式擁有多個執行流程。例如:有多個執行流程。例如: WebWeb 瀏覽程式可瀏覽程式可以在下載網頁檔案的同時顯示動畫、播放以在下載網頁檔案的同時顯示動畫、播放音樂或捲動視窗瀏覽網頁內容。音樂或捲動視窗瀏覽網頁內容。

Page 6: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2 Java10-2 Java 執行緒的使用方法執行緒的使用方法

10-2-1 10-2-1 實作實作 RunnableRunnable 介面介面10-2-2 10-2-2 繼承繼承 ThreadThread 類別類別

Page 7: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2 Java10-2 Java 執行緒的使用方法執行緒的使用方法

JavaJava 執行緒是建立執行緒是建立 ThreadThread 類別的物件,類別的物件,一共有一共有 22 種方式建立多執行緒應用程式,種方式建立多執行緒應用程式,如下所示:如下所示: 實作實作 RunnableRunnable 介面。介面。 繼承繼承 ThreadThread類別。類別。

Page 8: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2-1 10-2-1 實作實作 RunnableRunnable 介面介面 -- 架構架構

SwingSwing 應用程式繼承自應用程式繼承自 JFrameJFrame,, Java Java AppletApplet 繼承自繼承自 JAppletJApplet ,就只能實作,就只能實作RunnableRunnable 介面的介面的 run()run() 方法來建立多執行方法來建立多執行緒的應用程式,如下所示:緒的應用程式,如下所示:

class UserThread extends UserClass class UserThread extends UserClass implements Runnableimplements Runnable

{ { public UserThread(int length) { }public UserThread(int length) { } public void run() { ……… }public void run() { ……… }}}

Page 9: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2-1 10-2-1 實作實作 RunnableRunnable 介面介面 -- 啟動啟動

接著可以建立接著可以建立 ThreadThread 物件和啟動執行緒,物件和啟動執行緒,如下所示:如下所示:

UserThread ut1 = new UserThread(5);UserThread ut1 = new UserThread(5);

Thread t1 = new Thread(ut1, "Thread t1 = new Thread(ut1, " 執行緒執行緒 A");A");

t1.start();t1.start();

上述程式碼在建立好上述程式碼在建立好 UserThreadUserThread 物件物件 ut1ut1後,使用後,使用 ut1ut1 物件建立物件建立 ThreadThread 物件的執行物件的執行緒,參數字串是執行緒名稱,最後使用緒,參數字串是執行緒名稱,最後使用start()start() 方法啟動執行緒。方法啟動執行緒。

Page 10: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2-1 10-2-1 實作實作 RunnableRunnable 介面介面 -- 建構建構子子

ThreadThread 類別的建構子,如下表所示:類別的建構子,如下表所示:建構子 說明Thread()

Thread(String)Thread(Runnable)

Thread(Runnable, String)

建立 Thread物件,參數 String是執行緒名稱,Runnable是實作 Runnable介面的物件

Page 11: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2-1 10-2-1 實作實作 RunnableRunnable 介面介面 -- 相關相關方法方法

ThreadThread 類別的相關方法,如下表所示:類別的相關方法,如下表所示:方法 說明

int activeCount() 類別方法可以取得目前共有多少個執行中的執行緒

Thread currentThread() 類別方法可以取得目前的執行緒物件void sleep(long) 類別方法可以讓執行緒暫時停止執行一段時間,

也就是參數 long的毫秒數boolean isAlive() 檢查目前執行緒是否在執行中,傳回值 true為

是,false為不是void start() 啟動執行緒

void setName(String) 將執行緒指定為參數 String字串的名稱String getName() 取得執行緒的名稱字串String toString() 取得執行緒名稱、優先權和群組名稱字串,預設

的執行緒群組是 main

Page 12: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2-2 10-2-2 繼承繼承 ThreadThread 類別類別 -- 架構架構

若類別沒有繼承其他類別,就可以直接繼若類別沒有繼承其他類別,就可以直接繼承承 ThreadThread 類別,然後覆寫類別,然後覆寫 run()run() 方法建立方法建立執行緒物件,如下所示:執行緒物件,如下所示:

class UserThread extends Threadclass UserThread extends Thread{ { public UserThread(int length, String name) { }public UserThread(int length, String name) { } public void run() { ……… }public void run() { ……… }}}

Page 13: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-2-2 10-2-2 繼承繼承 ThreadThread 類別類別 -- 啟動啟動

接著就可以建立接著就可以建立 ThreadThread 物件,啟動執行緒,物件,啟動執行緒,如下所示:如下所示:

UserThread ut1 = UserThread ut1 =

new UserThread(5, "new UserThread(5, " 執行緒執行緒 A");A");

ut1.start();ut1.start();

上述程式碼在建立好上述程式碼在建立好 UserThreadUserThread 物件物件 ut1ut1後,這是後,這是 ThreadThread 物件,所以可以直接使用物件,所以可以直接使用start()start() 方法啟動執行緒。方法啟動執行緒。

Page 14: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-3 Java10-3 Java 執行緒的同步執行緒的同步 -- 說明說明

在第在第 10-210-2 節程式範例的執行緒間並沒有任節程式範例的執行緒間並沒有任何關係,簡單的說,執行緒的目的只是為何關係,簡單的說,執行緒的目的只是為了加速程式執行。另一種情況是執行緒間了加速程式執行。另一種情況是執行緒間擁有生產和消費者的關係或是同時存取相擁有生產和消費者的關係或是同時存取相同資源,當有此情況,就需要考量「同同資源,當有此情況,就需要考量「同步」(步」( SynchronizationSynchronization )問題。)問題。

Page 15: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-3 Java10-3 Java 執行緒的同步執行緒的同步 -- 生產者和生產者和消費者模型消費者模型

生產者和消費者模型(生產者和消費者模型( Producer/Consumer Producer/Consumer ModelModel ))生產者和消費者模型是指一個執行緒產生資料,生產者和消費者模型是指一個執行緒產生資料,稱為生產者,另一個執行緒讀取生產者產生的資稱為生產者,另一個執行緒讀取生產者產生的資料,稱為消費者,產生的資料是儲存在共用的資料,稱為消費者,產生的資料是儲存在共用的資料儲存緩衝區稱為「佇列」(料儲存緩衝區稱為「佇列」( QueueQueue ),這是一),這是一種先進先出的資料結構,如下圖所示:種先進先出的資料結構,如下圖所示:

Page 16: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-3 Java10-3 Java 執行緒的同步執行緒的同步 --synchronizedsynchronized 關鍵字關鍵字

synchronizedsynchronized 關鍵字關鍵字生產者和消費者是同步存取同一個資源物生產者和消費者是同步存取同一個資源物件,所以存取的件,所以存取的 enqueue()enqueue()和和 dequeue()dequeue()方法需要使用方法需要使用 synchronizedsynchronized 關鍵字鎖定資關鍵字鎖定資源,稱為同步方法(源,稱為同步方法( Synchronized MethoSynchronized Methodd ),如下所示:),如下所示:public synchronized void enqueue(int value)public synchronized void enqueue(int value){ …… }{ …… }public synchronized int dequeue()public synchronized int dequeue(){ …… }{ …… }

Page 17: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-3 Java10-3 Java 執行緒的同步執行緒的同步 -wait()-wait()和和notify()notify() 方法方法 (( 說明說明 ))

wait()wait()和和 notify()notify() 方法方法同步執行緒雖然使用同步執行緒雖然使用 synchronizedsynchronized 關鍵子關鍵子避免同時存取相同物件,但是為了讓生產避免同時存取相同物件,但是為了讓生產者產生的資料有地方儲存,且消費者能夠者產生的資料有地方儲存,且消費者能夠取得資料,有兩種情況需要特別處理,如取得資料,有兩種情況需要特別處理,如下所示:下所示: 佇列空了:佇列空了:如果佇列空了,消費者需要等待生如果佇列空了,消費者需要等待生

產者產生資料。產者產生資料。 佇列滿了:佇列滿了:如果佇列滿了,表示已經沒有地方如果佇列滿了,表示已經沒有地方

儲存,生產者需要等待消費者讀取資料。儲存,生產者需要等待消費者讀取資料。

Page 18: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-3 Java10-3 Java 執行緒的同步執行緒的同步 -wait()-wait()和和notify()notify() 方法方法 (enqueue()(enqueue() 方法方法 ))

public synchronized void enqueue(int value)public synchronized void enqueue(int value){ try // { try // 如果佇列已滿如果佇列已滿 { while ( queue.isFull() ){ while ( queue.isFull() ) {{ wait(); // wait(); // 等待等待 }} }} catch ( InterruptedException e ) { }catch ( InterruptedException e ) { } queue.enqueue(value); // queue.enqueue(value); // 存入存入 notify(); // notify(); // 通知通知 dequeue()dequeue()}}

Page 19: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-3 Java10-3 Java 執行緒的同步執行緒的同步 -wait()-wait()和和notify()notify() 方法方法 (dequeue()(dequeue() 方法方法 ))

public synchronized int dequeue()public synchronized int dequeue()

{ try // { try // 如果佇列已空如果佇列已空 { while(queue.isEmpty()){ while(queue.isEmpty())

{ wait(); // { wait(); // 等待 等待 }}

}}

catch ( InterruptedException e ) { }catch ( InterruptedException e ) { }

int data = queue.dequeue(); // int data = queue.dequeue(); // 取出取出 notify(); // notify(); // 通知通知 enqueue()enqueue()

return data;return data;

}}

Page 20: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-3 Java10-3 Java 執行緒的同步執行緒的同步 -wait()-wait()和和notify()notify() 方法方法 (( 相關方法相關方法 ))

ObjectObject 類別的相關方法,如下表所示:類別的相關方法,如下表所示:方法 說明

void wait()void wait(long)

讓執行緒等待,直到 notify()或 notifyAll()方法喚醒,參數 long表示不論是否被前面方法喚醒,在等待指定的毫秒數後也會被喚醒

void notify() 喚醒一個呼叫 wait()方法的執行緒void notifyAll() 喚醒所有呼叫 wait()方法的執行緒

Page 21: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒

10-4 10-4 管道串流的執行緒管道串流的執行緒

Java I/OJava I/O套件的套件的 PipedInputStreamPipedInputStream和和PipedOutputStreamPipedOutputStream管道串流類別是管道串流類別是InputStreamInputStream和和 OutputStreamOutputStream的子類別,的子類別,能夠建立類似第能夠建立類似第 10-310-3節生產者和消費者模節生產者和消費者模型的型的 JavaJava應用程式。應用程式。PipedInputStreamPipedInputStream和和 PipedOutputStreamPipedOutputStream管道串流類別能夠在一個執行緒產生資料管道串流類別能夠在一個執行緒產生資料寫入寫入 PipedOutputStreamPipedOutputStream串流物件,然後串流物件,然後在另一個執行緒從在另一個執行緒從 PipedInputStreamPipedInputStream串流串流物件讀取資料。物件讀取資料。

Page 22: 第 10 章 Java 的執行緒 10-1 執行緒的基礎 10-2 Java 執行緒的使用方法 10-3 Java 執行緒的同步 10-4 管道串流的執行緒