Java多線程應用開發(二)

多線程開發不僅提升了了程序執行的效率,更是大大解決了單線程中所無法解決的同步問題,那麼多線程開發是不是真的像我們想象的那麼完美呢?

       最近兩個星期一直在做多線程開發,期間用多線程達到了許多還算nice的效果,但是同時,也出現了許多新的問題,下面簡單的分析了一下:

1.  線程創建是否越多越好?怎麼樣提高效率?

舉一個多線程搜索的例子,寫一個搜索文件後綴的方法:

publicvoid searchSuffix(String suffix,String directory){

       //搜索指定路徑的文件夾

       File dir=new File(directory);

       if(dir.exists()){

           if(dir.isFile()&&dir.getName().startsWith(suffix)){

              System.out.println(dir.getAbsolutePath());

           }

           if(dir.isDirectory()){

              File files[]=dir.listFiles();

              int length=files.length;

              for(int i=0;i<length;i++){

                  //如果是以指定頭文件開頭的話,就輸出文件的絕對路徑

                  if(files[i].getName().endsWith(suffix)){

                     System.out.println(files[i].getAbsolutePath());

                  }

                  //如果仍然是一個目錄

                  if(files[i].isDirectory()){

                     //遞歸搜索該文件夾下面的文件

                     searchSuffix(suffix,files[i].getAbsolutePath());

                  }

              }

           }

       }

       else{

           System.out.println("路徑不存在");

       }

}

使用普通的單線程搜索時,搜索文件的方法是線性的,而且每搜索完一層目錄才能繼續搜索下一層的目錄,這樣程序執行的效率肯定不是很高。一個簡單的方法就是同時搜索該文件夾下面的第一層目錄,這樣能夠線性的提高程序的執行效率,例如,如果一個文件夾第一層下面有五個文件夾,那麼就同時搜索這五個文件夾,效率提高將達到小於五倍的效果(線程創建需要開銷)。同時,問題也就出現了,如果文件夾下面依然是單個文件夾,那麼這個做法就沒有意義了。在這種情況下我曾想到一個比較極端的做法,遞歸的創建線程搜索,爲每一個文件夾都創建一個線程來搜索該目錄下的文件,因爲在一般情況下,主文件夾下面的所有文件夾的數量一般比文件的數量要少得多,不過實際情況並不像想象中的那麼美妙。做一道簡單的計算題來證明一下:

假設創建一個線程的時間開銷相當於搜索五個文件的時間,多線程執行速度與單線程呈小於簡單logn的關係,遞歸算法執行沒有時間浪費,那麼在一般的文件夾下,文件的數量超出文件夾數量的五倍還是極有可能的,但是我們在遞歸的時候卻沒有考慮到程序判斷也需要時間,執行判斷語句無疑就將線程的創建時間開銷增加了大於一倍,由於線程越多,每一個線程執行的速度肯定也沒有單線程執行的速度要快,那麼文件數量至少要達到文件夾數量的二十倍以上纔會節約時間。聽到這裏你肯定會覺得,隨便一個文件夾裏面的文件還是很有可能超越文件夾的二十倍呀?但是我們沒有考慮過在超越一百個線程之後,這種理想的情況是否還會成立,或者實際上,線程過多早已導致你的程序溢出了棧空間。

有問題纔會新的發現,千萬不要把多線程當做提高運行效率的萬靈藥,過多的線程不僅會導致程序溢出棧空間,而且系統開銷也是相當之大。有一個比較經典的問題是如何讓自己的CPU使用率達到100%,在單核系統之下只用幾行代碼就可以實現(有興趣的可以嘗試一下),而我一直以爲自己的四核電腦是不會那麼輕易被“玩死”的,結果那天在多線程編程裏面調用了URL資源之後,CPU瞬間就被“玩死“了,這一點至今倒成了我比較有成就感的一件事。

      

2.如何讓線程聽你指揮?

多線程編程的時候,經常遇到的問題還有如何控制線程的掛起,合理的創建程並控制線程的運行與停止狀態可以達到許多nice的效果。

java6以後Thread類裏面的暫停(suspend,停止(stop)與重啓(resume)方法已經過時,原因是這些方法都有死鎖傾向,如果使用這些方法導致的結果很有可能就是線程的確是停止了,但是卻再也啓動不起來了,這個時候這個線程也就報廢了,那麼怎麼控制線程的執行與停止呢?我們可以使用如下的方法,也能達到預期的效果哦:

publicclass MyThread extends Thread{

    booleanisStop=false;//判斷線程是否停止

    booleanisPause=false;//判斷線程是否停止

    publicvoid run(){

       while(!isStop){//如果沒停止

           while(!isPause){//如果沒暫停

             

           }

       }

    }

}

到時候我們只要通過改變isStopisPause的值就可以控制線程是否執行了,是不是很方便呢?

多線程開發還有很多值得挖掘的地方,有時候用其解決的問題確實讓人興奮,不過其中帶來的麻煩卻也不少,這麼說來,多線程有些時候倒還真像一位美麗的女子,讓人歡喜讓人憂,當然,這樣的比喻倒不是太恰當,期待更多的發現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章