2013年7月14日 星期日

多執行緒程式設計

多執行緒程式設計

多執行緒程式設計

已更新的 今日

多執行緒程式設計

Java提供許多執行緒程式設計(multithreaded programming),Multithreaded program包含兩個或多個可同步執行的部分,它的每一個部分都稱為一個執行緒(thread),因此,它是一種多工(multitasking)的特殊形式。

多工的工作方式:
  1. 以程序為基礎(process-based)
    • 本質上,process就是指正在執行的程式
    • 通常程式就是排程器所能分派(dispatch)的最小單位
    • 通常用以做重量級(heavyweight)工作的處理,需要有自己的位址空間
    • 程序間溝通消耗許多資源
  2. 以執行緒為基礎(thread-based)
    • thread為可分派的最小單位
    • 單一程式可以同時執行兩個以上的工作
    • 多處理輕量級(lightweight)工作
    • 消耗資源較程序處理小,共用相同位址空間
    • 一起使用相同的重量級程序,彼此溝通所耗資源較小,執行緒間切畫布用消耗太多資源

Java的執行緒模型
  • Java的所有類別函式庫都將multithread列入考量。
  • Java利用thread將整個環境變成非同步(asynchronous)。避免CPU週期所造成的浪費,有助於提升整體效率。

同步
  • 若兩個執行緒需要互相溝通,並且共用某個複雜的資料結構,就必須確保執行緒使用的資料是一致的。
  • Java利用monitor來達到這個目的,monitor只能容納一個執行緒,一旦一個執行緒進入monitor,其他的執行緒必須等待,直到這個執行緒離開。
  • monitor可用以保護共用資源,避免同一時間被多個執行緒操縱

建立執行緒
  • Java的執行緒是建立於Thread類別、他的方法,以及Runnable介面的基礎上
  • Thread將執行緒封裝
  • 無法直接參考正在執行的執行緒之狀態,必須透過產生該執行緒的Thread實體來處理
  • 若要建立執行緒,你需要繼承Thread類別或者實作Runnable介面。
  • 實作Runnable Interface
    • Runnable將一組可執行的程式碼抽象化
    • 可以在任何時做Runnable的物件上建構執行緒
    • 若要實作Runnable,執行要實作一個稱為run()的方法
      • public void run()
      • 在run()裡,你將定義構成新執行緒的程式碼
      • run()為另一個同時在程式中執行的thread建立進入點
      • 當run()回傳時,此執行緒將會結束
    • 在你建立一個實作Runnable的類別後,你將利用此類別建立Thread型別的物件實體
    • Thread定義許多建構式,其中一個如下
      • Thread(Runnable threadOb, String threadName)
        • threadOb:實作Runnable介面的類別實體。它定義了thread的進入點
        • threadName:指定新執行緒的名稱
      • 新執行緒建立後,必須呼叫Thread定義的start()方法,新的執行緒才會開始執行。
        • 本質上Start()會呼叫run()方法:若直接呼叫run()方法,則只是單純的方法呼叫,而不會啟動新的執行緒
        • start方法如下所示:void start()
    • 以下範例示範如何建立新的執行緒,並使之開始執行:
      • public class NewThread implements Runnable {
        Thread t ;
        public NewThread() {
        // TODO Auto-generated constructor stub
        t= new Thread (this, "Demo Thread");
        System. out. println("Child thread: " +t );
        t. start();
        }
        @Override
        public void run() {
        // TODO Auto-generated method stub
        try {
        for(int i=5;i>0;i--){
        System. out. println("Child Thread" +i );
        Thread. sleep(500 );
        }
        } catch (InterruptedException e) {
        // TODO: handle exception
        System. out. println("Exiting child thread." );
        }

        }

        }
      • //主程式
      • public class ThreadDemo {
        public static void main(String args[]) {
        new NewThread ();
        try {
        for(int i=5;i>0;i--){
        System. out. println("Main Thread: " +i );
        Thread. sleep(1000 );
        }
        } catch (InterruptedException e) {
        // TODO: handle exception
        System. out. println("Main thread interrupted." );
        }
        System. out. println("Main thread exiting." );
        }
        }
      • 在NewThread的建構式中
        • t=new Thread (this,"Demo Thread");
        • 將this當作第一個引數,表示你希望新的thread呼叫this物件上的run()

主執行緒(main thread)
  • 當Java程式開始執行時,有一個執行緒會立即開始執行,此執行緒稱之程式的主執行緒
    • 子執行緒都是由主執行緒產生
    • 通常它必須是最後一個完成的執行緒,因為它會進行許多關閉的動作
  • 透過currentTread()方法可以獲得主執行緒的參考,其為Class Thread的public static member
    static Thread currentThread()
  • 執行緒範例程式:
    public class CurrentThreadDemo {
    public static void main(String args[]) {
    Thread t =Thread .currentThread();
    System. out. println("Current Thread:" +t );
    t. setName("Main Thread" );
    System. out. println("After name change:" +t );
    try {
    for ( int n = 5; n > 0; n--) {
    System. out. println(n );
    Thread. sleep(1000 );
    }
    } catch (InterruptedException e) {
    // TODO: handle exception
    System. out. println("Main thread interrupted" );
    }
    }
    }
    • 將t透過println()印出,依次會顯示
      • 執行緒名稱:主執行緒名稱預設為main
      • 優先權:主執行緒優先權預設為5
      • 所屬群組名稱:執行緒群組(thread group)是一種資料結構,可把一群執行緒當成一個整體來控制
    • static void sleep(long milliseconds) throws InsterruptedException
      • milliseconds:執行緒暫停的毫秒數
      • InsterruptedException :當其他執行緒試圖中斷(interrupt)處於睡眠狀態的執行緒時,會發生此意外
      • sleep()的第二種形式,可以毫秒以及十億分之秒的方式指定暫停時間
        • static void sleep(long milliseconds,int nanoseconds) throws InsterruptedException
        • 只在計時週期小於十億分之秒的環境有效
    • final void setName(String threadName):設定執行緒名稱
    • final String getName():取得執行緒名稱
儲存至 Evernote

沒有留言:

張貼留言

此部落格主要作為學習研究、心得分享,歡迎大家討論指教...