一、实现目的
本地目录下有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不吝赐教!若我的思路方面有何问题,也请共同探讨。

解决方案 »

  1.   

    采用多线程, 把这个目录里所有的文件名或者文件对象压入一个vector,然后notifyALl()
      

  2.   

    支持 zgysc(翠湖寒) !其实就是构造一个线程池和工作队列,把每个文件作为一个任务,让线程池里的线程来分别处理每个任务。不需要文件锁定,因为根本就不会冲突。请参考 http://www-128.ibm.com/developerworks/cn/java/j-jtp0730/
      

  3.   

    我这样实现的,处理一个文件,就开一个线程,可以达到我的要求,但是系统资源开销太大了。
    把这个目录里所有的文件对象压入一个vector,然后用线程池处理吗?我看了一下maquan('ma:kju) 老兄给我看的线程池,感觉思路方面还是不清晰,能具体说明一下如何实现吗?
      

  4.   

    zgysc(翠湖寒),能不能接着再谈一下你的想法
      

  5.   

    每个线程处理一个文件恐怕不合适,如果文件多于1000个,系统将很慢。
    建议把文件名放入List中(等同于编号),用固定的线程数,比如10个,每个线程分别处理一批文件(比如第0号线程处理0/10/20....)
      

  6.   

    请楼主看一下我这段程序。WorkQueue 基本来自于我前面给出的那个网址,我在其中加入了 quitWhenEmpty 是为了让程序最后能退出。那个 MyTask 就是用来处理每个文件的类,为了让它的运行时间显得长一点,我加了 1 秒的延迟。你可以把你的“计数程序”写在这里。另外,类似的功能在 java.util.concurrent 包里已经实现了(从 JDK1.5 开始)。package test;import java.io.File;
    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();
            }
        }}
      

  7.   

    问题不就是避免对同一个文件的重复处理吗???既然文件名都是形如"ex+年+月+日.log",当然是每天一个文件了。
    读文件列表是免不了的。
    那么在读时做一个处理,记录一个最早时间和一个最晚时间。
    然后,按照分了多少个线程,把这个时间区间均分成几段,一段分配给一个线程。
    每个线程按照它被分配到的时间小区间来取文件,如果文件名含有的日期不在所分配的区间里就略过,在就处理。
      

  8.   

    刚才没看其它回复
    现在看了下,发现 hbwhwang(catmiw的ID已经停用,现在用这个) 说的意思和我一样,他的方法更简便。
      

  9.   

    从下往上看的, 原来 zgysc(翠湖寒) 的队列,意思也差不多
    形式不同,效果都一样
      

  10.   

    TO theforever(碧海情天):老兄大概没看出来,我上面给出的程序,就是那两位老兄的意思的一个具体实现,hehe  *_*