一、实现目的
本地目录下有100个(或更多)的文本文件,文件名都是形如"ex+年+月+日.log",文件名是唯一的.文件内容的格式是每一行形如"[2006-08-28 09:10:10]XXXXXXX www.XX.com",现想用程序实现统计这100个日志文件中有多少个如"www.cscn.com"。
二、现我已实现程序顺序执行统计这些文件,一共有多个"www.cscn.com".但是如果文件比较多,内容也很多的话,执行时间比较慢。所以在这里我想用线程的并发统计。我用了java.nio.channels.FileLock类,在一个线程访问一个文件时,将该文件锁定。以阻止其它进程访问到该文件,避免数据统计的重复。
三、问题是java.nio.channels.FileLock类,"以整个 Java 虚拟机来保持。但它们不适用于控制同一虚拟机内多个线程对文件的访问。多个并发线程可安全地使用文件锁定对象",这是JDK帮助中的原话,我测试了,确实FileLock没有对其它进行访问文件起到作用。在此希望能实现该目的的TX不吝赐教!若我的思路方面有何问题,也请共同探讨。
本地目录下有100个(或更多)的文本文件,文件名都是形如"ex+年+月+日.log",文件名是唯一的.文件内容的格式是每一行形如"[2006-08-28 09:10:10]XXXXXXX www.XX.com",现想用程序实现统计这100个日志文件中有多少个如"www.cscn.com"。
二、现我已实现程序顺序执行统计这些文件,一共有多个"www.cscn.com".但是如果文件比较多,内容也很多的话,执行时间比较慢。所以在这里我想用线程的并发统计。我用了java.nio.channels.FileLock类,在一个线程访问一个文件时,将该文件锁定。以阻止其它进程访问到该文件,避免数据统计的重复。
三、问题是java.nio.channels.FileLock类,"以整个 Java 虚拟机来保持。但它们不适用于控制同一虚拟机内多个线程对文件的访问。多个并发线程可安全地使用文件锁定对象",这是JDK帮助中的原话,我测试了,确实FileLock没有对其它进行访问文件起到作用。在此希望能实现该目的的TX不吝赐教!若我的思路方面有何问题,也请共同探讨。
把这个目录里所有的文件对象压入一个vector,然后用线程池处理吗?我看了一下maquan('ma:kju) 老兄给我看的线程池,感觉思路方面还是不清晰,能具体说明一下如何实现吗?
建议把文件名放入List中(等同于编号),用固定的线程数,比如10个,每个线程分别处理一批文件(比如第0号线程处理0/10/20....)
import java.util.LinkedList;public class WorkQueue { private final int nThreads;
private final PoolWorker[] threads;
private final LinkedList queue; private boolean quitWhenEmpty;
public boolean isQuitWhenEmpty() { return quitWhenEmpty; }
public void setQuitWhenEmpty(boolean quitWhenEmpty) { this.quitWhenEmpty = quitWhenEmpty; } public WorkQueue(int nThreads) {
this.nThreads = nThreads;
quitWhenEmpty = false;
queue = new LinkedList();
threads = new PoolWorker[nThreads]; for (int i = 0; i < nThreads; i++) {
threads[i] = new PoolWorker();
threads[i].start();
}
} public void execute(Runnable r) {
synchronized (queue) {
queue.addLast(r);
queue.notify();
}
} private class PoolWorker extends Thread {
public void run() {
Runnable r; while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
if (quitWhenEmpty)
return; try {
queue.wait();
} catch (InterruptedException ignored) {
}
} r = (Runnable) queue.removeFirst();
} // If we don't catch RuntimeException,
// the pool could leak threads
try {
r.run();
} catch (RuntimeException e) {
// You might want to log something here
}
}
}
} public static void main(String[] args) {
WorkQueue queue = new WorkQueue(5);
File dir = new File(".");
for (File f : dir.listFiles()) {
queue.execute(new MyTask(f.getAbsolutePath()));
}
queue.setQuitWhenEmpty(true);
}}class MyTask implements Runnable { private String filename; public MyTask(String filename) {
this.filename = filename;
} public void run() {
try {
File f = new File(filename);
if (f.exists()) {
if (f.isDirectory())
System.out.println("[" + f.getCanonicalPath() + "] is dir ");
else
System.out.println("[" + f.getCanonicalPath() + "]: " + f.length());
}
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}}
读文件列表是免不了的。
那么在读时做一个处理,记录一个最早时间和一个最晚时间。
然后,按照分了多少个线程,把这个时间区间均分成几段,一段分配给一个线程。
每个线程按照它被分配到的时间小区间来取文件,如果文件名含有的日期不在所分配的区间里就略过,在就处理。
现在看了下,发现 hbwhwang(catmiw的ID已经停用,现在用这个) 说的意思和我一样,他的方法更简便。
形式不同,效果都一样