第16章java的執行緒 - dns2.asia.edu.twdns2.asia.edu.tw/~wzyang/slides/java_net/ch16.pdf ·...

12
16 16Java Java的執行緒 的執行緒 16 16Java Java的執行緒 的執行緒 執行緒的基礎 執行緒的基礎 16 16-1 1 執行緒的基礎 執行緒的基礎 16 16-2 Java 2 Java執行緒的使用方法 執行緒的使用方法 16 16 2 Java 2 Java執行緒的使用方法 執行緒的使用方法 16 16-3 Java 3 Java執行緒的同步 執行緒的同步 16 16-4 4 Java Applet Java Applet建立執行緒 建立執行緒 16 16-5 5 管道串流的執行緒 管道串流的執行緒 16 16 5 5 管道串流的執行緒 管道串流的執行緒 16 16 1 執行緒的基礎 執行緒的基礎 16 16-1 1 執行緒的基礎 執行緒的基礎 的執行緒 的執行緒 16 16-1-1 Java 1 Java的執行緒 的執行緒 16 16-1-2 2 多工與多執行緒 多工與多執行緒 16 16 1 2 2 多工與多執行緒 多工與多執行緒

Upload: others

Post on 15-Oct-2019

6 views

Category:

Documents


0 download

TRANSCRIPT

  • 第第1616章章 JavaJava的執行緒的執行緒第第1616章章 JavaJava的執行緒的執行緒

    執行緒的基礎執行緒的基礎1616--1 1 執行緒的基礎執行緒的基礎1616--2 Java2 Java執行緒的使用方法執行緒的使用方法1616 2 Java2 Java執行緒的使用方法執行緒的使用方法1616--3 Java3 Java執行緒的同步執行緒的同步1616--4 4 在在Java AppletJava Applet建立執行緒建立執行緒1616--5 5 管道串流的執行緒管道串流的執行緒1616 5 5 管道串流的執行緒管道串流的執行緒

    1616 11 執行緒的基礎執行緒的基礎1616--1 1 執行緒的基礎執行緒的基礎

    的執行緒的執行緒1616--11--1 Java1 Java的執行緒的執行緒1616--11--2 2 多工與多執行緒多工與多執行緒1616 11 2 2 多工與多執行緒多工與多執行緒

  • 1616 11 1 Java1 Java的執行緒的執行緒 說明說明1616--11--1 Java1 Java的執行緒的執行緒--說明說明

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

    1616 11 1 Java1 Java的執行緒的執行緒 多執行緒多執行緒1616--11--1 Java1 Java的執行緒的執行緒--多執行緒多執行緒

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

  • 1616 11 22 多工與多執行緒多工與多執行緒1616--11--2 2 多工與多執行緒多工與多執行緒

    目前的目前的作業系統作業系統都強調都強調「多工「多工目前的目前的作業系統作業系統都強調都強調「多工」「多工」((MultitaskingMultitasking)。)。例如:微軟的例如:微軟的WindowsWindows作業作業系統屬於一套多工的作業系統 可以系統屬於一套多工的作業系統 可以同時執行同時執行小小系統屬於一套多工的作業系統,可以系統屬於一套多工的作業系統,可以同時執行同時執行小小畫家、記事本和小算盤等畫家、記事本和小算盤等多個應用程式多個應用程式

    不同於作業系統的多工,不同於作業系統的多工,「多執行緒」「多執行緒」不同於作業系統的多工不同於作業系統的多工 多執行緒」多執行緒」((MultithreadedMultithreaded))是指在是指在單一應用程式單一應用程式擁有擁有多多個執行流程個執行流程。例如:。例如:WebWeb瀏覽程式瀏覽程式可以在可以在下載網下載網個執行流程個執行流程 例如例如 WebWeb瀏覽程式瀏覽程式可以在可以在下載網下載網頁檔案頁檔案的同時的同時顯示動畫顯示動畫、、播放音樂播放音樂或或捲動視窗瀏捲動視窗瀏覽網頁內容覽網頁內容。。覽網頁內容覽網頁內容

    1616 2 Java2 Java執行緒的使用方法執行緒的使用方法1616--2 Java2 Java執行緒的使用方法執行緒的使用方法

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

  • 1616 2 Java2 Java執行緒的使用方法執行緒的使用方法1616--2 Java2 Java執行緒的使用方法執行緒的使用方法

    執行緒是建立執行緒是建立 類別類別的物件 一的物件 一JavaJava執行緒是建立執行緒是建立ThreadThread類別類別的物件,一的物件,一共有共有22種方式種方式建立多執行緒應用程式,如下建立多執行緒應用程式,如下所示:所示:

    •• 實作實作RunnableRunnable介面介面。。•• 實作實作RunnableRunnable介面介面。。•• 繼承繼承ThreadThread類別類別。。

    1616 22 11 實作實作RunnableRunnable介面介面 架構架構1616--22--1 1 實作實作RunnableRunnable介面介面--架構架構S iS i 應用程式繼承自應用程式繼承自JFJF J A l tJ A l t繼繼SwingSwing應用程式繼承自應用程式繼承自JFrameJFrame,,Java AppletJava Applet繼繼承自承自JAppletJApplet,就只能,就只能實作實作RunnableRunnable介面的介面的run()run()方法來建立多執行緒的應用程式:方法來建立多執行緒的應用程式:方法來建立多執行緒的應用程式:方法來建立多執行緒的應用程式:

    class UserThread class UserThread extends UserClassextends UserClassimplements Runnableimplements Runnableimplements Runnableimplements Runnable

    { // { // 建構子建構子bli U Th d(i t l th) { }bli U Th d(i t l th) { }public UserThread(int length) { }public UserThread(int length) { }

    // // 執行執行緒執行執行緒public void public void run()run(){ { ……………… }}

    }}

  • 1616 22 11 實作實作RunnableRunnable介面介面 啟動啟動1616--22--1 1 實作實作RunnableRunnable介面介面--啟動啟動

    接著可以建立接著可以建立 物件和啟動執行緒物件和啟動執行緒接著可以建立接著可以建立ThreadThread物件和啟動執行緒:物件和啟動執行緒:UserThread UserThread ut1ut1 = new UserThread(5);= new UserThread(5);UserThread UserThread ut1ut1 new UserThread(5); new UserThread(5);Thread t1 = new Thread(Thread t1 = new Thread(ut1ut1, ", "執行緒執行緒A");A");t1t1 start()start();;t1.t1.start()start();;

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

    1616--22--1 1 實作實作RunnableRunnable介面介面--建構建構子子

    類別的建構子 如下表所示類別的建構子 如下表所示ThreadThread類別的建構子,如下表所示:類別的建構子,如下表所示:

    建構子 說明建構子 說明

    Thread()Thread(String)

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

    Thread(Runnable)Thread(Runnable, String)

    是實作 介面的物件

  • 1616--22--1 1 實作實作RunnableRunnable介面介面--相關相關方法方法

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

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

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

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

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

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

    的執行緒群組是 main

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

    class UserThread class UserThread extends Threadextends Thread{ // { // 建構子建構子{ // { // 建構子建構子

    public UserThread(int length, String name) public UserThread(int length, String name) { }{ }{ }{ }// // 執行執行緒執行執行緒public void public void run()run(){ { ……………… }}

    }}

  • 1616 22 22 繼承繼承ThreadThread類別類別 啟動啟動1616--22--2 2 繼承繼承ThreadThread類別類別--啟動啟動

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

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

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

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

    1616 3 Java3 Java執行緒的同步執行緒的同步 說明說明1616--3 Java3 Java執行緒的同步執行緒的同步--說明說明

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

  • 1616--3 Java3 Java執行緒的同步執行緒的同步--生產者和消生產者和消費者模型費者模型

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

    1616--3 Java3 Java執行緒的同步執行緒的同步--synchronizedsynchronized關鍵字關鍵字

    h i dh i d關鍵字關鍵字synchronizedsynchronized關鍵字關鍵字生產者和消費者是同步存取同一個資源物生產者和消費者是同步存取同一個資源物件,所以件,所以存取的存取的enqueue()enqueue()和和dequeue()dequeue()方法需要使用方法需要使用synchronizedsynchronized關鍵字鎖定資關鍵字鎖定資yy源源,稱為同步方法(,稱為同步方法(Synchronized Synchronized MethodMethod),如下所示:),如下所示:et odet od) 如下所示) 如下所示public public synchronizedsynchronized void enqueue(int void enqueue(int

    value)value)value)value){ { ………… }}public public synchronizedsynchronized int dequeue()int dequeue()public public synchronizedsynchronized int dequeue()int dequeue(){ { ………… }}

  • 1616--3 Java3 Java執行緒的同步執行緒的同步--wait()wait()和和notify()notify()方法方法((說明說明))

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

    •• 佇列滿了佇列滿了::如果佇列滿了,表示已經沒有地方如果佇列滿了,表示已經沒有地方儲存,生產者需要等待消費者讀取資料。儲存,生產者需要等待消費者讀取資料。儲存 生產者需要等待消費者讀取資料儲存 生產者需要等待消費者讀取資料

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

    bli h i d id (i t l )bli h i d id (i t l )public synchronized void enqueue(int value)public synchronized void enqueue(int value){ try { try // // 如果佇列已滿如果佇列已滿

    { while ( { while ( queue.isFull()queue.isFull() )){{{{

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

    }}catch ( InterruptedException e ) { }catch ( InterruptedException e ) { }catch ( InterruptedException e ) { }catch ( InterruptedException e ) { }queue.enqueue(value); // queue.enqueue(value); // 存入存入notify(); // notify(); // 通知通知dequeue()dequeue()notify(); // notify(); // 通知通知dequeue()dequeue()

    }}

  • 1616--3 Java3 Java執行緒的同步執行緒的同步--wait()wait()和和notify()notify()方法方法((dequeue()dequeue()方法方法))

    p bli n h oni ed int deq e e()p bli n h oni ed int deq e e()public synchronized int dequeue()public synchronized int dequeue(){ try { try // // 如果佇列已空如果佇列已空

    { hile(q e e{ hile(q e e isEmpt ()isEmpt ())){ while(queue.{ while(queue.isEmpty()isEmpty())){{

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

    }}}}catch ( InterruptedException e ) { }catch ( InterruptedException e ) { }int data queue dequeue(); // int data queue dequeue(); // 取出取出int data = queue.dequeue(); // int data = queue.dequeue(); // 取出取出notify(); // notify(); // 通知通知enqueue()enqueue()return data;return data;return data;return data;

    }}

    1616--3 Java3 Java執行緒的同步執行緒的同步--wait()wait()和和notify()notify()方法方法((相關方法相關方法))類別的相關方法 如下表所示類別的相關方法 如下表所示ObjectObject類別的相關方法,如下表所示:類別的相關方法,如下表所示:

    方法 說明方法 說明

    void wait()void wait(long)

    讓執行緒等待,直到 notify()或 notifyAll()方法喚醒,參數 long 表示不論是否被前面方法喚( g) 喚醒 參數 long 表示不論是否被前面方法喚

    醒,在等待指定的毫秒數後也會被喚醒

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

  • 1616--4 4 在在Java AppletJava Applet建立建立執行緒執行緒--架構架構

    因為繼承自因為繼承自 類別 所類別 所Java AppletJava Applet因為繼承自因為繼承自JAppletJApplet類別,所類別,所以在以在Java AppletJava Applet建立執行緒,一定是建立執行緒,一定是實作實作ppppRunnableRunnable介面介面,如下所示:,如下所示:

    public class Ch16 4 public class Ch16 4 extends JAppletextends JAppletpublic class Ch16_4 public class Ch16_4 extends JAppletextends JAppletimplements Runnableimplements Runnable

    { { ……………… }}

    1616--4 4 在在Java AppletJava Applet建立執行緒建立執行緒--啟動啟動

    在實作在實作 方法後 就可以在方法後 就可以在 方法方法在實作在實作run()run()方法後,就可以在方法後,就可以在start()start()方法方法建立執行緒物件和啟動執行緒,如下所示:建立執行緒物件和啟動執行緒,如下所示:

    public void start()public void start(){ th d Th d(thi ){ th d Th d(thi ){ thread = new Thread(this);{ thread = new Thread(this);

    thread.start();thread.start();thread.start();thread.start();}}

  • 1616 55 管道管道串流的執行緒串流的執行緒1616--5 5 管道管道串流的執行緒串流的執行緒

    J I/OJ I/O套件的套件的Pi dPi dI tStI tSt 和和Java I/OJava I/O套件的套件的PipedPipedInputStreamInputStream和和PipedPipedOutputStreamOutputStream管道串流類別是管道串流類別是

    SS 和和O SO S 的子類別的子類別InputStreamInputStream和和OutputStreamOutputStream的子類別,的子類別,能夠建立類似第能夠建立類似第1616--33節生產者和消費者模節生產者和消費者模型的型的 應用程式應用程式型的型的JavaJava應用程式。應用程式。PipedInputStreamPipedInputStream和和ped putSt eaped putSt ea 和和PipedOutputStreamPipedOutputStream管道串流類別能夠在管道串流類別能夠在一個執行緒產生資料寫入一個執行緒產生資料寫入一個執行緒產生資料寫入一個執行緒產生資料寫入PipedOutputStreamPipedOutputStream串流物件,然後在串流物件,然後在另另一個執行緒一個執行緒從從PipedInputStreamPipedInputStream串流物串流物一個執行緒一個執行緒從從PipedInputStreamPipedInputStream串流物串流物件讀取資料件讀取資料。。