1 / 74

課程參與度之評估方式

課程參與度之評估方式. 上課時必須專心聽講,跟上進度,參與討論 扣 分項目 玩線上遊戲一次扣 1 分 玩手機一次扣 1 分 睡覺一次扣 1 分 聊天一次扣 1 分 無法回答老師提出的問題一次扣 1 分 加分項目 主動回答老師的問題一次加 2 分 找出老師程式中的錯誤一次加 1 分 修正老師程式中的錯誤一次加 4 分. 網路程式設計 第七章 多執行緒程式設計. 鄧姚文. 大綱. 執行緒 繼承 Thread 類別 實作 Runnable 介面 三匹馬的賽事 管理執行緒 伺服器的多執行緒. 前言. 多執行緒程式設計 多個執行緒可以模擬出平行處理的效果

Download Presentation

課程參與度之評估方式

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 課程參與度之評估方式 • 上課時必須專心聽講,跟上進度,參與討論 • 扣分項目 • 玩線上遊戲一次扣1分 • 玩手機一次扣1分 • 睡覺一次扣1分 • 聊天一次扣1分 • 無法回答老師提出的問題一次扣1分 • 加分項目 • 主動回答老師的問題一次加2分 • 找出老師程式中的錯誤一次加1分 • 修正老師程式中的錯誤一次加4分

  2. 網路程式設計第七章 多執行緒程式設計 鄧姚文

  3. 大綱 執行緒 繼承Thread類別 實作Runnable介面 三匹馬的賽事 管理執行緒 伺服器的多執行緒

  4. 前言 • 多執行緒程式設計 • 多個執行緒可以模擬出平行處理的效果 • 將一個CPU的執行時間切割為很小的單位,將這些單位分給多個行程去使用 • 模擬出多工(multi-task)的效果

  5. 只有一個CPU實體 分時多工: 三個行程同時執行

  6. 前言 • main執行緒 • 一個可以執行的Java類別,在main這個特別的方法被執行時,就建立了一個執行緒 • main方法的開始到結束 • 若設計一個賽馬的程式,就只能讓一匹馬從起點跑到終點

  7. 7-1 執行緒 • 執行緒的四種狀態 • 執行中(Running) • 正在執行中 • 暫停(Suspended) • 暫時停止執行,稍後可以繼續執行(Resume) • 被阻擋(Blocked,卡住?) • 因所需資源被其他執行緒占用,進入等待狀態 • 終止(Terminated) • 停止執行,無法再繼續執行

  8. 7-1 執行緒 • Thread類別的方法 • java.lang.Thread讓設計者向作業系統取得執行緒 • 以此包裝待執行的工作 • 繼承 Thread 類別即可讓新類別具備執行緒功能

  9. Thread類別的方法

  10. 7-1 執行緒 • main方法也是個執行緒 • 每個Java應用程式都至少擁有一個執行緒 • currentThread() 可取得目前執行緒物件

  11. 7-1 執行緒 01 package com.ch07; 02 03 public class ThreadName { 04 public static void main(String[] args) { 05 Thread thr = Thread.currentThread(); 06 System.out.println("目前執行緒名稱:"+thr.getName()); 07 thr.setName("DEMO"); 08 System.out.println("更改後的名稱:"+thr.getName()); 09 } 10 } ▌執行結果 目前執行緒名稱:main 更改後的名稱:DEMO

  12. 7-1 執行緒 • 兩匹馬賽跑 • 若只使用main方法來設計賽馬的程式,不能達到需求 • 利用for迴圈讓兩匹馬(整數h1與h2)從0加到5000,看那匹馬先到終點(5000)

  13. 兩匹馬賽跑 • 03 public class RacingNG { • 04 public static void main(String[] args) { • 05 int h1 = 0; • 06 int h2 = 0; • 07 for (inti=0; i<5000; i++){ • 08 h1++; • 09 h2++; • 10 System.out.println("H1:"+h1); • 11 System.out.println("H2:"+h2); • 12 } • 13 } • 14 }

  14. 兩匹馬假賽跑 • 執行結果,每一次執行一定是h1先到達終點 • (省略) • H1:4996 • H2:4996 • H1:4997 • H2:4997 • H1:4998 • H2:4998 • H1:4999 • H2:4999 • H1:5000 • H2:5000

  15. 7-1 執行緒 • 兩匹馬假賽跑 • 每次執行結果都一樣,不符合實際需求 • 應該把h2的工作(從0加到5000)「搬到」另一個執行緒去處理 • 讓main執行緒與新執行緒一起執行

  16. 7-2 繼承Thread類別 新增一個Horse類別並繼承Thread 覆寫Thread的run()方法 將要執行的工作程式碼放在run()方法內

  17. 7-2 繼承Thread類別 • 產生執行緒並執行 • 將Horse類別建構出來後,再呼叫其方法start() ,即可啟動這個執行緒

  18. 跑馬執行緒程式碼 01 package com.ch07; 02 03 public class Horse extends Thread{ 04 //覆寫Thread方法run() 05 public void run(){ 06 //由1跑到5000 07 int h = 0; 08 for (inti=0; i<5000; i++){ 09 h++; 10 System.out.println(getName()+":"+h); 11 } 12 } 13 }

  19. 7-2 繼承Thread類別 • 產生執行緒並執行 • 因此,讀者可修改原程式Racing類別,在未開始執行迴圈之前,生出Horse類別的物件,再啟動這個執行緒:

  20. 跑馬主程式 01 package com.ch07; 02 03 public class Racing { 04 public static void main(String[] args) { 05 int h1 = 0; 06 //產生Horse物件並啟動執行緒 07 Horse h2 = new Horse(); 08 h2.start(); 09 for (inti=0; i<5000; i++){ 10 h1++; 11 System.out.println("H1:"+h1); 12 } 13 } 14 }

  21. 7-2 繼承Thread類別 • 產生執行緒並執行 • 程式碼與執行緒之間的示意圖如下:

  22. 7-2 繼承Thread類別 (省略) H1:4995 H1:4996 H1:4997 H1:4998 H1:4999 H1:5000 Thread-0:1496 Thread-0:1497 Thread-0:1498 Thread-0:1499 (省略) • 多次執行結果不同 • h2執行緒比main還早執行完成

  23. 7-2 繼承Thread類別 (省略) Thread-0:4998 Thread-0:4999 Thread-0:5000 H1:1053 H1:1054 H1:1055 H1:1056 H1:1057 (省略) • 多次執行結果不同 • main執行緒較h2早執行完成

  24. 7-3 實作Runnable介面 JAVA 限制單一繼承,如果自訂類別已經有繼承對象,便無法再繼承 Thread 藉由「實作Runnable介面」建立執行緒

  25. 7-3 實作Runnable介面 • implementsRunnable • 實作 run()方法 • 上節的Horse改用介面實作,新類別為HorseRunnable

  26. 7-3 實作Runnable介面 01 package com.ch07; 02 03 public class HorseRunnable implements Runnable { 04 public void run() { 05 int h = 0; 06 for (inti=0; i<5000; i++){ 07 h++; 08 System.out.println(h); 09 } 10 } 11 } implementsRunnable

  27. 7-3 實作Runnable介面 • 啟動Runnable介面執行緒 • 產生執行緒類別的物件 • HorseRunnable h3 = new HorseRunnable(); • 利用Thread類別建構子中的其中一個可接收參數Runnable物件的建構子 • Thread thr = new Thread( h3 ); • 呼叫Thread物件的start()方法 • thr.start();

  28. 7-4 三匹馬的賽事 讓main方法專心處理產生執行緒與計算賽馬名次等工作 三匹馬都以Horse執行緒來執行 在main方法中產生三個Horse執行緒物件

  29. 7-4 三匹馬的賽事 01 package com.ch07; 02 03 public class Racing3 { 04 public static void main(String[] args) { 05 Horse h1 = new Horse(); 06 Horse h2 = new Horse(); 07 Horse h3 = new Horse(); 08 h1.setName("h1"); 09 h2.setName("h2"); 10 h3.setName("h3"); 11 h1.start(); 12 h2.start(); 13 h3.start(); 14 System.out.println("main執行緒結束"); 15 } 16 }

  30. 7-4 三匹馬的賽事 • sleep方法 • sleep(long millis) • sleep方法使用時必須以try...catch處理被意外中斷的例外InterruptedException

  31. 三匹馬的賽事 01 package com.ch07; 02 03 public class Horse extends Thread { 04 // 覆寫Thread方法run() 05 public void run() { 06 try { 07 sleep(2000); 08 System.out.println("到達終點"); 09 } catch (InterruptedException e) { 10 System.out.println("被中斷了"); 11 } 12 } 13 }

  32. 7-4 三匹馬的賽事 ▌執行Racing3類別的結果如下(每次結果有可能不一樣) main執行緒結束 h1到達終點 h3到達終點 h2到達終點 • sleep方法 • 可以讓main等待三個Horse執行緒都完成後,才結束嗎?

  33. 7-4 三匹馬的賽事 h2到達終點 h3到達終點 h1到達終點 main執行緒結束 • join()方法-等待 • Thread類別的方法join(),可以用來等待該執行緒完成

  34. 以 join 讓 main 等待執行緒結束 01 package com.ch07; 02 03 public class Racing3_2 { 04 public static void main(String[] args) { 05 Horse h1 = new Horse(); 06 Horse h2 = new Horse(); 07 Horse h3 = new Horse(); 08 h1.setName("h1"); 09 h2.setName("h2"); 10 h3.setName("h3"); 11 h1.start(); 12 h2.start(); 13 h3.start(); 14 try {

  35. 以 join 讓 main 等待執行緒結束 15 h1.join(); 16 h2.join(); 17 h3.join(); 18 } catch (InterruptedException e) { 19 System.out.println("執行緒被中斷"); 20 } 21 System.out.println("main執行緒結束"); 22 } 23 }

  36. 結算賽馬的名次- Racing4 01 package com.ch07; 02 03 import java.util.Vector; 04 05 public class Racing4 { 06 public static void main(String[] args) { 07 Vector<RankHorse> rank = new Vector<RankHorse>(); 08 RankHorse h1 = new RankHorse(rank); 09 RankHorse h2 = new RankHorse(rank); 10 RankHorse h3 = new RankHorse(rank); 11 h1.setName("h1"); 12 h2.setName("h2"); 13 h3.setName("h3"); 14 h1.start(); 15 h2.start(); 16 h3.start(); 17 try { 18 h1.join();

  37. 結算賽馬的名次- Racing4 19 h2.join(); 20 h3.join(); 21 } catch (InterruptedException e) { 22 System.out.println("執行緒被中斷"); 23 } 24 System.out.println(rank); 25 System.out.println("main執行緒結束"); 26 } 27 }

  38. 01 package com.ch07; 02 import java.util.Vector; 03 04 public class RankHorse extends Thread { 05 Vector<RankHorse> rank ; 06 07 public RankHorse(Vector<RankHorse> rank){ 08 this.rank = rank; 09 } 10 11 //覆寫Thread方法run() 12 public void run(){ 13 try { 14 sleep(2000); 15 System.out.println(getName()+"到達終點"); 16 //放進rank集合中 17 rank.add(this); 18 } catch (InterruptedException e) { 19 System.out.println(getName()+"被中斷了"); 20 } 21 } 22 }

  39. 7-4 三匹馬的賽事 h1到達終點 h3到達終點 h2到達終點 [Thread[h1,5,], Thread[h3,5,], Thread[h2,5,]] main執行緒結束 • Racing4類別的執行結果如下,可以看到rank集合內依照到達順序的三匹馬:

  40. 7-5 管理執行緒 • 優先權值(Priority) • 為執行緒訂定「優先權值(Priority)」,優先權值較高的執行緒會較快進入執行的階段 • 執行緒的優先權值可以利用setPriority方法改變,亦可使用getPriority方法取得執行緒目前的優先權值。 • Thread類別中定義了MAX_PRIORITY、NORM_PRIORITY與MIN_PRIORITY整數常數,代表了最高、普通、最低優先權值

  41. 優先權值(Priority)

  42. 優先權值(Priority) 01 package com.ch07; 02 03 public class PriorityTester { 04 public static void main(String[] args) { 05 Thread thr = new Thread(); 06 //印出thr目前的優先權值 07 System.out.println("thr目前的優先權值:"+thr.getPriority()); 08 //變更為最高優先權 09 thr.setPriority(Thread.MAX_PRIORITY); 10 System.out.println("thr目前的優先權值:"+thr.getPriority()); 11 //變更優先權值為8 12 thr.setPriority(8); 13 System.out.println("thr目前的優先權值:"+thr.getPriority()); 14 } 15 } ▌執行結果 thr目前的優先權值:5 thr目前的優先權值:8

  43. 7-5 管理執行緒 • 執行緒的對列(queue) • 執行緒的sleep()或yeild()方法被呼叫時,會暫停目前的工作,並進入執行緒的隊列(ready queue)排隊等待下一次CPU的執行單位

  44. 7-5 管理執行緒 • public synchronizedvoid thunder(){ • //程式碼 • } • 資源的鎖定 • 避免多個執行緒存取同一個資源 • Java語言利用「同步方法(method-level)」與「同步區塊(block-level)」這兩個方式 • 同步方法 • 為一個類別的方法加上synchronized修飾字 • 限定在同一時間,只能由此一個物件使用這個方法

  45. 7-5 管理執行緒 • synchronized( 物件 ){ • 程式碼 • 程式碼 • } • 資源的鎖定 • 同步區塊 • 限定只能由單一執行緒能執行某段程式碼 • 必需指定一個需要同步的物件

  46. 7-6 伺服器的多執行緒 以main執行緒為每個客戶端程式產生執行緒,以處理個別的需求。 設計一個執行緒,可分別處理每個客戶端的需求

  47. 7-6 伺服器的多執行緒 01 package com.ch07; 02 03 import java.io.IOException; 04 import java.net.ServerSocket; 05 import java.net.Socket; 06 07 public class EchoServer { 08 public static void main(String[] args) { 09 try { 10 ServerSocket server = new ServerSocket(3333); 11 Socket socket = server.accept(); 12 } catch (IOException e) { 13 e.printStackTrace(); 14 System.out.println("伺服器窗口發生錯誤"); 15 } 16 } 17 } 多執行緒伺服器的設計

  48. 7-6 伺服器的多執行緒 01 package com.ch07; 02 03 public class EchoThread extends Thread { 04 public void run() { 05 06 } 07 } • 設計EchoThread執行緒 • 初期設計

  49. 7-6 伺服器的多執行緒 • 設計EchoThread執行緒 • 設計一建構子,接收java.net.Socket

  50. 01 package com.ch07; 02 03 import java.io.BufferedReader; 04 import java.io.IOException; 05 import java.io.InputStreamReader; 06 import java.io.OutputStreamWriter; 07 import java.io.PrintWriter; 08 import java.net.Socket; 09 10 public class EchoThread extends Thread { 11 BufferedReader in ; 12 PrintWriter out ; 13 public EchoThread(Socket ss) throws IOException{ 14 in = new BufferedReader(new 15 InputStreamReader(ss.getInputStream())); 16 out = new PrintWriter( 17 new OutputStreamWriter(ss.getOutputStream())); 18 } 19 public void run() { 20 21 } 22 }

More Related