日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

文件目录遍历的并发算法

發布時間:2024/8/24 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 文件目录遍历的并发算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題:算出指定目錄下文件的大小.

這個是個很簡單的問題嘛,直接做個遞歸就行,上順序算法:

public long getFileSize(final File file){if(file.isFile()){return file.length();}else{long total = 0;File files[] = file.listFiles();if(files == null)return 0;for(File f: files){total += getFileSize(f);}return total;}}

很簡單,一個遞歸實現,那么現在我們思考并發的算法

并發思路:每次進行遞歸運算,每次開一個線程去計算當前目錄的文件大小,然后進行遞歸運算

并發代碼:

private long getFileSizebf(final ExecutorService service,final File file) throws InterruptedException, ExecutionException, TimeoutException{if(file.isFile())return file.length();else{final File files[] = file.listFiles();if(files == null)return 0;else{long total = 0;final List<Future<Long>> tasks = new ArrayList<Future<Long>>();for(final File f : files){tasks.add(service.submit(new Callable<Long>() {@Overridepublic Long call() throws Exception {// TODO Auto-generated method stub
                //進行遞歸,把子目錄的文件大小返回
return getFileSizebf(service, f);}}));}for(final Future<Long> fl : tasks){total += fl.get();}return total;}}}

看上去沒什么問題,我們來實際測試下;

我們看到,調用get從Future中取數據的時候,并沒有設置超時,實際運行中發現,當文件夾的目錄結構簡單,目錄樹比較淺的時候能夠跑出來,但是目錄樹結構復雜了以后,跑了很久還是跑不出來結果.

分析:我們每個線程會開啟新的線程去計算子目錄的大小,這個時候,線程會進入等待,等待子線程的返回結果,這個時候就會出現一種情況,假如目錄樹的結構復雜,那么很多線程會進入等待狀態,等待子線程的返回值,但是這些父線程還是占用著線程池,但是子線程請求不到線程池去執行,這個時候就會進入死鎖.

如下圖:

優化策略:1.既然是線程池的poolsize不夠用了,那么我們就增加poolsize的大小嘛,好了,現在我們面對的是一個目錄結構不那么復雜的,通過簡單地增加poolsize還可以做到,但是非常復雜的話就沒辦法了.

2.我們之所以會造成死鎖,是因為線程在占用線程池的情況下同時在等待子線程的返回結果,

優化版本1:

public class FileOPBX1 implements FileOpI {@Overridepublic long getTotalSizeOfFilesInDir(File f) {long total = 0;final ExecutorService eService = Executors.newFixedThreadPool(100);// TODO Auto-generated method stubfinal List<File> dirs = new ArrayList<>();dirs.add(f);//初始化當前文件夾while (!dirs.isEmpty()) {//每次計算dir里面一集目錄下的文件大小以及子目錄final List<Future<SubDirAndSize>> part = new ArrayList<>();for (final File dir : dirs) {part.add(eService.submit(new Callable<SubDirAndSize>() {@Overridepublic SubDirAndSize call() throws Exception {// TODO Auto-generated method stubreturn getEveryDir(dir);}}));}dirs.clear();//目錄分配任務完畢,清除//從返回的結果計算文件大小,并且把新的子目錄添加到待計算文件夾for (final Future<SubDirAndSize> subdir : part) {try {final SubDirAndSize sas = subdir.get();total += sas.size;dirs.addAll(sas.subDirs);} catch (InterruptedException | ExecutionException e) {// TODO Auto-generated catch block e.printStackTrace();}}System.out.println(dirs);}return total;}//計算當前一級目錄下文件的大小以及子目錄private SubDirAndSize getEveryDir(final File f) {long total = 0;final List<File> subDirs = new LinkedList<File>();if (f.isDirectory()) {final File[] sub = f.listFiles();if (sub != null) {for (final File dir : sub) {if (dir.isFile())total += dir.length();else {subDirs.add(dir);}}}}return new SubDirAndSize(total, subDirs);}public class SubDirAndSize {final public long size;final public List<File> subDirs;public SubDirAndSize(final long totalsize, final List<File> thesubDir) {size = totalsize;subDirs = Collections.unmodifiableList(thesubDir);}}}

這個時候我們看結果:

運行花費時間9688
串行執行結果:19563974028
運行花費時間3230
并行執行結果:19563974028

?

轉載于:https://www.cnblogs.com/color-my-life/p/4352551.html

總結

以上是生活随笔為你收集整理的文件目录遍历的并发算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。