java 多线程 扫描,多线程扫描文件夹耗时方法分析

在这里Java的方法中有线程递归,不懂得用什么方法求运行时间遇到一个有趣的问题,多线程扫描文件夹求运行时间。一般这种扫描文件夹耗时好像都是用的递归遍历一下进行计时,头一次看到这种一个文件夹一个线程的,这里按照原问题楼主的想法试着解决一下。

刚开始我是采用静态变量,共享总耗时,把每个run方法耗时都加上。

package com.brewin.codetuning.test;

import java.io.File;

import java.text.SimpleDateFormat;

import java.util.Date;

public class ThreadDemo02

{

public static void main(String args[]) {

File file=new File("D:\\AA");

MyThread mt1 = new MyThread("线程1",file);

mt1.start();

}

}

class MyThread extends Thread

{

private String name;

private File file;

public static int sum;

static {

sum = 0;

}

public MyThread(String name,File file) {

this.name = name;

this.file=file;

}

@Override

public void run() {

long startTime = System.currentTimeMillis();

File[] files=file.listFiles();

if(files!=null &&files.length>0) {

for(File f:files) {

if(f.isDirectory()) {

new MyThread(f.getName(),f).start();

}

// 打印文件名不方便看最后的耗时打印,注释掉

// else {

// System.out.println(Thread.currentThread().getName()+":"+f);

// }

}

}

// try {

// Thread.sleep(5000);

// }

// catch (InterruptedException e) {

// // TODO Auto-generated catch block

// e.printStackTrace();

// }

long endTime = System.currentTimeMillis();

long usedTime = (endTime-startTime);

sum+=usedTime;

System.out.println(name + " 运行结束,耗时: "+usedTime+" ms,sum现为:" +MyThread.sum+" ms");

}

}

控制台打印的什么呢?下面截取最后一部分

storage 运行结束,耗时: 0 ms,sum现为:3156 ms

x509 运行结束,耗时: 1 ms,sum现为:3157 ms

implementations 运行结束,耗时: 1 ms,sum现为:3158 ms

implementations 运行结束,耗时: 1 ms,sum现为:3159 ms

但是实际并没有用到3秒多,很快就结束了。

下面是加了Thread.sleep(5000)的结果,更明显一些:

xs 运行结束,耗时: 5004 ms,sum现为:2611580 ms

implementations 运行结束,耗时: 5001 ms,sum现为:2606576 ms

traversers 运行结束,耗时: 5001 ms,sum现为:2616581 ms

多线程是并发执行,所以这个思路是错误的,不能计算他们的总和,而是要计算他们的最开始的时间和最后的时间。改变思路,在最开始时初始化一个开始时间,后面每次线程结束后都更新一下最后时间,求他们之间的差值就可以了。

package com.brewin.codetuning.test;

import java.io.File;

public class ThreadDemo02

{

public static void main(String args[]) {

File file=new File("D:\\AA");

MyThread mt1 = new MyThread("线程1",file);

mt1.start();

}

}

class MyThread extends Thread

{

private static long startTime;

private String name;

private File file;

static {

startTime = System.currentTimeMillis();

}

public MyThread(String name,File file) {

this.name = name;

this.file=file;

}

@Override

public void run() {

File[] files=file.listFiles();

if(files!=null &&files.length>0) {

for(File f:files) {

if(f.isDirectory()) {

new MyThread(f.getName(),f).start();

}

// 打印文件名不方便看最后的耗时打印,注释掉

// }else {

// System.out.println(Thread.currentThread().getName()+":"+f);

// }

}

}

long usedTime = System.currentTimeMillis()-startTime;

System.out.println(name + " 运行结束,已耗时: "+usedTime+" ms");

}

}

控制台最后一段打印如下:

io 运行结束,已耗时: 164 ms

proxy 运行结束,已耗时: 164 ms

dom 运行结束,已耗时: 164 ms

serialize 运行结束,已耗时: 165 ms

fsm 运行结束,已耗时: 165 ms

rmi 运行结束,已耗时: 166 ms

spi 运行结束,已耗时: 166 ms

tree 运行结束,已耗时: 166 ms

graph 运行结束,已耗时: 166 ms

util 运行结束,已耗时: 166 ms

utils 运行结束,已耗时: 167 ms

protocol 运行结束,已耗时: 167 ms

implementations 运行结束,已耗时: 167 ms

http 运行结束,已耗时: 167 ms

content 运行结束,已耗时: 167 ms

resolver 运行结束,已耗时: 167 ms

util 运行结束,已耗时: 168 ms

identity 运行结束,已耗时: 168 ms

keyvalues 运行结束,已耗时: 168 ms

x509 运行结束,已耗时: 169 ms

xs 运行结束,已耗时: 169 ms

serializer 运行结束,已耗时: 169 ms

util 运行结束,已耗时: 169 ms

xs 运行结束,已耗时: 169 ms

util 运行结束,已耗时: 169 ms

validation 运行结束,已耗时: 170 ms

undo 运行结束,已耗时: 170 ms

traversers 运行结束,已耗时: 170 ms

util 运行结束,已耗时: 170 ms

namingutil 运行结束,已耗时: 170 ms

exceptions 运行结束,已耗时: 170 ms

CORBA 运行结束,已耗时: 171 ms

xpath 运行结束,已耗时: 171 ms

transforms 运行结束,已耗时: 171 ms

utils 运行结束,已耗时: 171 ms

params 运行结束,已耗时: 171 ms

encryption 运行结束,已耗时: 171 ms

signature 运行结束,已耗时: 171 ms

output 运行结束,已耗时: 171 ms

implementations 运行结束,已耗时: 172 ms

closure 运行结束,已耗时: 172 ms

concurrent 运行结束,已耗时: 172 ms

orbutil 运行结束,已耗时: 172 ms

helper 运行结束,已耗时: 172 ms

keyresolver 运行结束,已耗时: 172 ms

storage 运行结束,已耗时: 172 ms

implementations 运行结束,已耗时: 173 ms

implementations 运行结束,已耗时: 173 ms

resolver 运行结束,已耗时: 173 ms

implementations 运行结束,已耗时: 173 ms

models 运行结束,已耗时: 174 ms

implementations 运行结束,已耗时: 174 ms

opti 运行结束,已耗时: 174 ms

text 运行结束,已耗时: 174 ms

rtf 运行结束,已耗时: 174 ms

utils 运行结束,已耗时: 175 ms

giopmsgheaders 运行结束,已耗时: 175 ms

reference 运行结束,已耗时: 175 ms

regex 运行结束,已耗时: 175 ms

threadpool 运行结束,已耗时: 175 ms

res 运行结束,已耗时: 176 ms

html 运行结束,已耗时: 177 ms

parser 运行结束,已耗时: 177 ms

看到原问题楼主有提到CountDownLatch ,找来文章看了一下,不是很适合这里,CountDownLatch计数器的初始大小要跟任务数的大小一致(跟线程数无关),每执行一次任务,计数器减一(countDown),await()方法会一直阻塞主线程,直到计数器的值减为0,才会释放锁,如此便可以达到确保所有任务都完成才继续下一步的效果。

但是本文场景是不断递归new出新线程,并且本文场景中要求任务数和线程数是相等的,无法确定任务数,就没办法初始化CountDownLatch 大小。

想要用CountDownLatch 的话只能加个统计方法,获得文件夹数量,如下:

package com.brewin.codetuning.test;

import java.io.File;

import java.util.concurrent.CountDownLatch;

public class ThreadDemo02

{

static int count;

static {

count = 0;

}

public static void main(String args[]) {

File file = new File("D:\\AA");

countNumberOfFolders(file);

long startTime = System.currentTimeMillis();

MyThread mt1 = new MyThread("线程1", file);

mt1.start();

try {

MyThread.latch.await();

}

catch (InterruptedException e) {

e.printStackTrace();

}

long usedTime = System.currentTimeMillis() - startTime;

System.out.println("耗时: " + usedTime + " ms");

}

/**

* 统计文件夹数量

* @param f

* @exception/throws [违例类型] [违例说明]

* @see [类、类#方法、类#成员]

*/

public static void countNumberOfFolders(File f) {

count++;

File[] files = f.listFiles();

if (files != null && files.length > 0) {

for (File file : files) {

if (file.isDirectory()) {

countNumberOfFolders(file);

}

}

}

}

}

class MyThread extends Thread

{

private String name;

private File file;

static CountDownLatch latch;

static {

latch = new CountDownLatch(ThreadDemo02.count);

}

public MyThread(String name, File file) {

this.name = name;

this.file = file;

}

@Override

public void run() {

File[] files = file.listFiles();

if (files != null && files.length > 0) {

for (File f : files) {

if (f.isDirectory()) {

new MyThread(f.getName(), f).start();

}

// 打印文件名不方便看最后的耗时打印,注释掉

// }else {

// System.out.println(Thread.currentThread().getName()+":"+f);

// }

}

}

System.out.println(name + " 运行结束");

latch.countDown();

}

}

结果如下:

http 运行结束

output 运行结束

dom 运行结束

compiler 运行结束

util 运行结束

耗时: 350 ms

可以看到确实是等到所有的线程执行结束后才进行的下一步。

如上 结题

本作品采用《CC 协议》,转载必须注明作者和本文链接

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值