问题:算出指定目录下文件的大小.

这个是个很简单的问题嘛,直接做个递归就行,上顺序算法:

    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

文件目录遍历的并发算法相关推荐

  1. 非递归遍历二叉树(算法导论第三版第十章10.4-5)

    非递归遍历二叉树(算法导论第三版第十章10.4-5) template<typename T> void TraverseBinaryTreeNonRecursive(BinaryTree ...

  2. Android安全开发之ZIP文件目录遍历

    1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在"../"的字符串,攻击者可以利用多个"../"在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原 ...

  3. 二叉树广度和深度遍历的全部算法

    二叉树广度和深度遍历的全部算法 对于二叉树的遍历,有广度遍历和深度遍历两大类,对于深度遍历又分为先序.中序和后序,这三种先中后序又可以用递归和非递归两种算法来写,下面就分别对这两大类算法做个总结,以后 ...

  4. 北邮22信通:二叉树各种遍历所有常见算法汇总

    北邮22信通一枚~    跟随课程进度每周更新数据结构与算法的代码和文章  持续关注作者  解锁更多邮苑信通专属代码~ 获取更多文章  请访问专栏~ 北邮22信通_青山如墨雨如画的博客-CSDN博客 ...

  5. [免费专栏] Android安全之ZIP文件目录遍历漏洞

    也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 转移发布平台通知:将不再在CSDN博客发布新文章,敬请移步知 ...

  6. 使用计算机频繁使用的算法,基于DHP的频繁遍历路径挖掘算法-天津大学计算机学院.PDF...

    基于DHP的频繁遍历路径挖掘算法-天津大学计算机学院 维普资讯 第25卷第 5期 杭 州 电子 科 技 大 学 学报 Vo1.25.No.5 2005年 10月 Jounud of I-la~ hou ...

  7. c语言 迷宫深度遍历 算法,图的遍历迷宫生成算法浅析

    1. 引言 在平常的游戏中,我们常常会碰到随机生成的地图.这里我们就来看看一个简单的随机迷宫是如何生成. 2. 迷宫描述随机生成一个m * n的迷宫,可用一个矩阵maze[m][n]来表示,如图:   ...

  8. morris算法(莫里斯遍历) [数据结构与算法]

    morris算法(莫里斯算法) Morris算法, 我们最常用于解决二叉树的遍历问题, 以及与遍历相关的一些问题(其实在二叉树系列问题中, 我们解决各种问题的时候都要涉及到一个对二叉树的遍历) 我们先 ...

  9. 树的前序、中序、后序遍历及深度优先算法DFS、广度优先算法BFS及python实现

    刷Leetcode时遇到一种经典数据结构--树,树是典型递归思想来的,学习树有助于学习递归思想以及栈.队列(后续细说),本文对树的结构.遍历算法以及Python实现做总结,以供复习拓展 树是连通的无环 ...

最新文章

  1. Qt之QGraphicsView实战篇(很强大)
  2. Python-02-基础知识
  3. qos和被qos是什么意思
  4. 对字符串进行 匹配,查找,替换,判断。
  5. 操作数组的常用方式二-----排序、查找
  6. iOS-----线程同步与线程通信
  7. 2021年中国专业话筒市场趋势报告、技术动态创新及2027年市场预测
  8. java derby xsai2,java-j内的引用罐
  9. PHP数字格式化,每三位逗号分隔数字,可以保留小数
  10. 高通QCC3020应用开发的软件平台的搭建
  11. vrep与vs2015联合仿真(C/C++)
  12. Ansys-结构动力学分析-悬臂梁模态分析学习收获
  13. 陈玉琴老师的中医理学
  14. 自助装机配置专家点评3
  15. SNS背后的科:从六度分隔到无尺度网络,互联网营销
  16. mysql查询工龄在20年以上_数据库查询练习
  17. java游戏怎么导入jme3,java - JME:将带有纹理的Cinema 4d模型导入jMonkey Projekt - 堆栈内存溢出...
  18. lp_solve 线性规划求解包的使用
  19. 用html和css制作小黄人,CSS3 小黄人案例
  20. 输入一个整数x,判断其能否被3整除也被7整除。

热门文章

  1. [Oracle 学习] Oracle中将查询语句执行结果导入文本文件
  2. 我在学习技术的过程遇到的不会的单词(不断完善)
  3. VS.NET 2005真是太好用了!
  4. Openwrt配置ssh自动登录服务器socks5转发
  5. 从零开始学电脑_《新手从零开始学电脑》1.6——怎样才能打一手好字
  6. 设置计算机关机静音,Shortcuts 捷径控制 Windows 电脑:静音开关、音量调节、待机、关机...
  7. computed get set 传参_ES6 的 Set 与 Map深入理解
  8. P1216 [IOI1994][USACO1.5]数字三角形 Number Triangles(简单dp)
  9. hihocoder#1041 : 国庆出游(DFS)
  10. 因子和(类素数筛选法)