关于文件目录线程级深度优先搜索效率的研究
来源:互联网 发布:北京哪里有mac专柜 编辑:程序博客网 时间:2024/05/01 16:09
我承认标题很高大上,其实只是一个初中生的无聊研究。
ps:如果有建议,随便提。
正文:
试验方法:
不限制深度,但限制时间。在同一个根目录(C:\)开始搜索,过滤出dll文件,第一次用普通方法(单线程),记录查找到的文件数目,第二次用线程级的方法(多线程),一样记录数目。对比两次实验的结果,得到结论。
代码片段:
目录的深度优先算法(普通版的)(自写的,不知道是不是最优-->_-->):
public static Function<String, Predicate<File>> isendwith = s -> isDic.negate().and(f -> f.getName().toUpperCase().endsWith(s.toUpperCase())); private long size = 0; boolean stop = false; private void search(File f, int deepth, String n) { if (stop) { return; } //if(deepth <= 0) //return; File[] files = f.listFiles(); if (files == null) { return; } List<File> list = Arrays.asList(files); size += list.stream().filter(isendwith.apply(n)).count(); list.stream().filter(isDic).forEach(fi -> search(fi, deepth - 1, n)); list = null; files = null; }其中 stop 为控制是否结束的变量
线程版的(有点多):
第一个类:BLockingStack
一个线程安全的栈,用以存放搜索到的目录。用来放Inf类。
(原理参见,虽然是阻塞队列:http://www.cnblogs.com/yjmyzz/p/BlockingQueue-in-java.html)
import java.util.Stack;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.locks.ReentrantLock;import java.util.concurrent.locks.Condition;/** * * @author Administrator * @param <E> */public class BlockingStack<E> { private Stack<E> stack = null; private ReentrantLock lock = null; private Condition notEmpty = null; public BlockingStack(){ stack = new Stack(); lock = new ReentrantLock(false); notEmpty = lock.newCondition(); } public void push(E item) throws InterruptedException{ final ReentrantLock lock = this.lock; lock.lockInterruptibly(); checkisNull(item); stack.push(item); notEmpty.signal(); lock.unlock(); } public E pop() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try{ while(stack.isEmpty()) notEmpty.await(); return stack.pop(); }finally{ lock.unlock(); } } public E peek() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try{ while(stack.isEmpty()) notEmpty.await(); return stack.peek(); }finally{ lock.unlock(); } } private void checkisNull(E e){ if(e == null) throw new NullPointerException(); } }
第二个类:Inf
极其简单,用来储存一个File,一个deepth。
本来deepth是用来判断是否结束搜索的,但实验不限制深度,所以暂时没用。
public class Inf { File f = null; int deepth = -1; public Inf(File fi, int d){ f = fi; deepth = d; }}
第三类:FileSearcher
较为重要,是线程搜索的核心。
接受一个BLockingStack<Inf>,只是一个公共的栈,从中获取要搜索的目录。
LinkedList<File>,一个公共链表,用于储存结果。
String,过滤的文件后缀名。
ps:虽然代码中有两个synchronized,但我不知道是不是可以去掉。
结束的话先用interrupt,再用stopsearch
import java.io.File;import java.util.LinkedList;import java.util.logging.Level;import java.util.logging.Logger;/** * * @author Administrator */public class FileSearcher extends Thread{ private BlockingStack<Inf> dics = null; private LinkedList<File> files = null; private String sfx = null; private boolean stop = true; public FileSearcher(BlockingStack<Inf> d, LinkedList<File> f, String sfx){ dics = d; files = f; this.sfx = sfx; } public synchronized void stopsearch(){ stop = false; } private void search() throws InterruptedException { while(stop){ Inf inf = dics.pop(); final File[] fs = inf.f.listFiles(); if(fs != null){ synchronized(fs){ for(File f : fs){ if(f.isDirectory()) dics.push(new Inf(f, 0)); else if(f.getName().toUpperCase().endsWith(sfx.toUpperCase())) files.add(f); } } } } } @Override public void run() { try { search(); } catch (InterruptedException ex) { Logger.getLogger(FileSearcher.class.getName()).log(Level.SEVERE, null, ex); } }}
最后是条用的类(包含普通方法):
然后
import java.util.ArrayList;import java.util.List;import java.util.function.Predicate;import java.io.File;import java.util.Arrays;import java.util.LinkedList;import java.util.function.Function;import java.util.logging.Level;import java.util.logging.Logger;public class Test { private ArrayList<File> files = new ArrayList(64); public static Predicate<File> isDic = File::isDirectory; public static Function<String, Predicate<File>> isendwith = s -> isDic.negate().and(f -> f.getName().toUpperCase().endsWith(s.toUpperCase())); private long size = 0; public Test() { /*Thread t = new Thread() { @Override public void run() { search(new File("C:\\"), 0, ".dll"); } }; t.start(); try { Thread.sleep(10000); } catch (InterruptedException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } stop = true; System.out.println(size);*/ //以上是普通方法的调用,要创一个线程调用,主线程计时 BlockingStack<Inf> stack = new BlockingStack(); LinkedList<File> list = new LinkedList(); FileSearcher fs = new FileSearcher(stack, list, ".dll"); FileSearcher fs1 = new FileSearcher(stack, list, ".dll"); FileSearcher fs2 = new FileSearcher(stack, list, ".dll"); FileSearcher fs3 = new FileSearcher(stack, list, ".dll"); try { stack.push(new Inf(new File("C:\\"), 0)); fs.start(); fs1.start(); fs2.start(); fs3.start(); Thread.sleep(10000); fs.interrupt(); fs1.interrupt(); fs2.interrupt(); fs3.interrupt(); fs.stopsearch(); fs1.stopsearch(); fs2.stopsearch(); fs3.stopsearch(); } catch (InterruptedException ex) { Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex); } finally { System.out.println(list.size()); }<span style="white-space:pre"></span> //线程级方法调用,自动创建线程,主线程用于计时 } boolean stop = false; private void search(File f, int deepth, String n) { if (stop) { return; } //if(deepth <= 0) //return; File[] files = f.listFiles(); if (files == null) { return; } List<File> list = Arrays.asList(files); size += list.stream().filter(isendwith.apply(n)).count(); list.stream().filter(isDic).forEach(fi -> search(fi, deepth - 1, n)); list = null; files = null; }}
结果:
但是对比第一次与第二次的普通方法的结果,就尴尬了。
这次数越多,结果也越大。但还好,稳在了8千左右。
于是,我猜想,数量的增多是不是与磁盘优化,或系统提供的优化有关(如果有知道为啥的,回复一下,谢了)。于是有了13行的操作。
但然并卵,反而结果变大了,so,有了17行的操作。普通方法的结果终于降下来了。
数据的对比很明显了,线程级的效率高。但对比15,与16的数据,又尴尬了(#滑稽)。发现线程不是越多越好。
最后的结论是:
线程级的效率普遍高于普通方法,但2-3个线程足矣,不然会产生浪费。
ps:看到系统盘多余29600个dll我就方了。
- 关于文件目录线程级深度优先搜索效率的研究
- 关于基于邻接矩阵的深度优先搜索
- 关于深度优先搜索的运用
- 深度优先和广度优先搜索文件
- 关于深度优先搜索和广度优先搜索C语言的简明实现
- 关于图的广度优先搜索(BFS)和深度优先搜索(DFS)
- 深度优先搜索和深度优先搜索的区别
- 图的深度优先搜索
- 图的深度优先搜索
- 图的深度优先搜索
- 图的深度优先搜索
- 深度优先搜索的实现
- 图的深度优先搜索
- 图的深度优先搜索
- 邻接矩阵的深度优先搜索
- 图的深度优先搜索
- 图的深度优先搜索
- 深度优先搜索的学习
- Web前端性能优化(八)配置ETag
- 解决ubuntu下深度音乐和wine程序托盘图标的问题
- 欢迎使用CSDN-markdown编辑器
- 0.附录
- 1013
- 关于文件目录线程级深度优先搜索效率的研究
- Dijkstra算法(单源最短路问题)
- Web前端性能优化(九)图像和Cookie优化
- 最短编辑距离
- 用到MNIST数据集的实验(总结中……)
- 【LeetCode】 17. Letter Combinations of a Phone Number
- 学生信息系统之优化(一)之ascii码
- Codeforces 665C Simple Strings【暴力,贪心】
- linux命令