和風細雨

          世上本無難事,心以為難,斯乃真難。茍不存一難之見于心,則運用之術自出。

          線程的創(chuàng)建

          單線程程序

          一般來說,在沒有線程的幫助下,程序在一個時間段只能執(zhí)行一段代碼,其它代碼段只有在等待它完成后才能執(zhí)行。該程序的處理流程從頭到尾只有一條線,這樣的程序我們稱之為單線程程序(Single Thread Program)

          典型的單線程程序:
          public class SingleThreadProgram{
            public static void main(String[] args){
              for(int i=0;i<1000;i++){
                System.out.print("SingleThreadProgram");
              }
            }
          }

          多線程程序

          當程序由一個以上的線程所構(gòu)成時,稱此程序為多線程程序(Multithread Program),java從設計伊始就把程序的多線程能力列入了考慮范圍。
          典型的多線程程序有:

          1)GUI應用程序,我們目前做的Swing桌面程序就屬于此類。
          2)較花費時間的I/O處理,一般來說,文件和網(wǎng)絡的輸入/輸出處理比較花費時間,如果在這段無法進行其它處理,則程序性能會大打折扣,遇到這種情況首先要想到用多線程解決問題.
          3)多連接網(wǎng)絡處理。

          并發(fā)(Concurrent)與并行(Parallel)

          當有多個線程在操作時,如果系統(tǒng)只有一個CPU,則它根本不可能真正同時進行一個以上的線程,它只能把CPU運行時間劃分成若干個時間段,再將時間段分配給各個線程執(zhí)行,在一個時間段的線程代碼運行時,其它線程處于掛起狀態(tài).這種方式我們稱之為并發(fā)(Concurrent).
          當系統(tǒng)有一個以上CPU時,則線程的操作有可能非并發(fā).當一個CPU執(zhí)行一個線程時,另一個CPU可以執(zhí)行另一個線程,兩個線程互不搶占CPU資源,可以同時進行,這種方式我們稱之為并行(Parallel)



          多線程在并發(fā)和并行環(huán)境中的不同作用

          在并發(fā)環(huán)境時,多線程不可能真正充分利用CPU,節(jié)約運行時間,它只是以”掛起->執(zhí)行->掛起”的方式以很小的時間片分別運行各個線程,給用戶以每個線程都在運行的錯覺.在這種環(huán)境中,多線程程序真正改善的是系統(tǒng)的響應性能和程序的友好性.
          在并行環(huán)境中, 一個時刻允許多個線程運行,這時多線程程序才真正充分利用了多CPU的處理能力, 節(jié)省了整體的運行時間.在這種環(huán)境中,多線程程序能體現(xiàn)出它的四大優(yōu)勢:充分利用CPU,節(jié)省時間,改善響應和增加程序的友好性.

          PS:在多核時代來臨后,開發(fā)多線程程序的能力更是每個程序員都該具備的.

          創(chuàng)建多線程程序

          創(chuàng)建多線程程序我們通常有兩種方法:
          1)讓類繼承java.lang.Thread,這種方法優(yōu)勢在于調(diào)用稍微方便,一般用于后臺批處理程序的場合,但劣勢是類無法再繼承別的類。
          2)讓類實現(xiàn)接口java.lang.Runnable,這種方法調(diào)用時需要借助Thread的幫助,稍顯麻煩,但優(yōu)勢在于對類繼承體系沒有影響,這是使用線程時最常用的方法。
          兩種方法的線程執(zhí)行部分都在run()函數(shù)中,它們的效率沒有差別。

          多線程程序創(chuàng)建和啟動示例

          創(chuàng)建線程

          // 繼承Thread類
          public class Thread1 extends Thread{
            public void run(){
              while(true){
                System.out.println("<Thread1 extends Thread>");
              }
            }
          }

          // 實現(xiàn)Runnable接口
          public class Thread2 implements Runnable{
            public void run(){
              while(true){
                System.out.println("<Thread2 implements Runnable>");
              }
            }
          }

          啟動線程

          public class Main{
            public static void main(String[] args){
              // 啟動線程1,Thread1直接繼承自java.lang.Thread類
              Thread1 th1=new Thread1();
              th1.start();
             
              // 啟動線程2,thread2實現(xiàn)自java.lang.Runnable接口
              Thread2 thread2=new Thread2();
              Thread th2=new Thread(thread2);
              th2.start();
             
              while(true){
                System.out.println("<Main Thread>");
              }
            }
          }

          概念解析Start和Run

          public void run()
          這個函數(shù)容納線程啟動后執(zhí)行的代碼塊,線程啟動起來,run函數(shù)中的代碼會得到執(zhí)行.

          Thead.start()
          這是啟動一個線程的方法,調(diào)用了這個方法后,線程才會得到執(zhí)行.

          取得線程執(zhí)行的結(jié)果

          通過觀察run函數(shù)的簽名public void run()我們可以發(fā)現(xiàn),它既沒有輸入?yún)?shù),也沒有返回值,那如何取得線程的返回值呢?一般來說我們有三種辦法:
          1)讓線程修改公有變量,如某類的靜態(tài)公有字段.這種方式古老而危險,最好不要采用.
          2)輪詢線程執(zhí)行結(jié)果,線程執(zhí)行的結(jié)果放在線程類的一個字段中,外界不斷通過輪詢?nèi)ゲ榭磮?zhí)行結(jié)果.這種方式會浪費很多時間,結(jié)果也不可靠,不建議采用.
          3)回調(diào)方式,把調(diào)用方的指針通過線程類的構(gòu)造函數(shù)傳入線程類的一個字段中,當線程執(zhí)行完取得結(jié)果后再通過這個字段反向調(diào)用調(diào)用方的函數(shù).這是取得線程執(zhí)行結(jié)果的最佳解決方案.

          下面請看回調(diào)方式的實現(xiàn).

          Boss類
          這個類用于啟動Secretary線程去查找文件, findFile()是啟動線程并查找的函數(shù), giveBossResult(String file,String reult)是供Secretary類回調(diào)的函數(shù).

          public class Boss{
            private String name;
           
            public Boss(String name){
              this.name=name;
            }
           
            public void giveBossResult(String file,String reult){
              if(reult!=null){
                System.out.println("文件"+file+"序列號等于:"+reult);
              }
              else{
                System.out.println("無法找到文件"+file);
              }
            }
           
            public void findFile(){  
              Map<String,String> files=new Hashtable<String,String>();   
              files.put("001", "員工花名冊");
              files.put("002", "企業(yè)收支");
              files.put("003", "客戶花名錄");
              files.put("004", "對手狀況分析");
              files.put("005", "當月收支");
              files.put("006", "市場份額分析");
              files.put("007", "大連酒店一覽");
              files.put("008", "娛樂場所名錄");
              files.put("009", "關系單位聯(lián)系名錄");
             
              Secretary andy=new Secretary("Andy",this,"員工花名冊",files);
              Thread th1=new Thread(andy);
              th1.start();
             
              Secretary cindy=new Secretary("cindy",this,"上市情況分析",files);
              Thread th2=new Thread(cindy);
              th2.start();
            }
           
            public static void main(String[] args){
              Boss boss=new Boss("Bill");
              boss.findFile();
            }
          }

          Secretary類

          這個類是進行多線程查找文件的類,查找的結(jié)果通過回調(diào)方法告知Boss實例.
          Boss實例,查找的文件名,查找的集合都通過Secretary類的構(gòu)造函數(shù)傳進來.

          public class Secretary implements Runnable{
            private String name;
            private Boss boss;
            private String file;
            private Map<String,String> files;
           
            public Secretary(String name,Boss boss,String file,Map<String,String> files){
              this.name=name;
              this.boss=boss;
              this.file=file;
              this.files=files;
            }
           
            public void run(){
              for(Map.Entry<String,String> entry:files.entrySet()){
                   if(entry.getValue().equals(file)){
                     boss.giveBossResult(file,entry.getKey());
                     return;
                   }
              }
             
              boss.giveBossResult(file,null);
            }
          }

          posted on 2008-02-22 12:34 和風細雨 閱讀(1971) 評論(1)  編輯  收藏 所屬分類: 線程

          評論

          # re: 線程的創(chuàng)建 2008-08-02 16:55 天堂明月

          回調(diào)方式返回數(shù)據(jù)是個不錯的方法
            回復  更多評論   

          主站蜘蛛池模板: 疏附县| 福清市| 翁牛特旗| 安陆市| 神木县| 佛山市| 长治市| 巴林右旗| 衡南县| 全椒县| 六枝特区| 宁国市| 开化县| 婺源县| 孟津县| 天柱县| 化州市| 会同县| 濉溪县| 福州市| 托里县| 平凉市| 清远市| 平阳县| 永嘉县| 武威市| 衡南县| 太湖县| 双桥区| 周口市| 娄烦县| 福清市| 西华县| 亚东县| 响水县| 上蔡县| 衡阳市| 呈贡县| 双柏县| 中宁县| 乌兰浩特市|