2

我正在运行一个线程来遍历我的本地目录(没有子目录),一旦我得到一个文本文件,我就会开始一个新线程,它将在该文件中搜索一个单词。

下面的代码有什么问题?

搜索和遍历分别工作正常。但是当我把它放在一起时,有些事情出了问题,它正在跳过一些文件(不完全是,由于多线程对象同步没有正确发生)。

请帮帮我。

遍历.java

    public void executeTraversing() {
            Path dir = null;
            if(dirPath.startsWith("file://")) {
                    dir = Paths.get(URI.create(dirPath));
            } else {
                    dir = Paths.get(dirPath);
            }
            listFiles(dir);
    }

    private synchronized void listFiles(Path dir) {
            ExecutorService executor = Executors.newFixedThreadPool(1);
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
                    for (Path file : stream) {
                            if (Files.isDirectory(file)) {
                                    listFiles(file);
                            } else {
                                    search.setFileNameToSearch(file);
                                    executor.submit(search);
                            }
                    }
            } catch (IOException | DirectoryIteratorException x) {
                    // IOException can never be thrown by the iteration.
                    // In this snippet, it can only be thrown by
                    // newDirectoryStream.
                    System.err.println(x);
            }
    }

搜索.java

    /**
     * @param wordToSearch
     */
    public Search(String wordToSearch) {
            super();
            this.wordToSearch = wordToSearch;
    }

    public void run() {
            this.search();    
    }

    private synchronized void search() {
            counter = 0;

            Charset charset = Charset.defaultCharset();
            try (BufferedReader reader = Files.newBufferedReader(fileNameToSearch.toAbsolutePath(), charset)) {
                    // do you have permission to read this directory?
                    if (Files.isReadable(fileNameToSearch)) {
                            String line = null;
                            while ((line = reader.readLine()) != null) {
                                    counter++;
                                    //System.out.println(wordToSearch +" "+ fileNameToSearch);

                                    if (line.contains(wordToSearch)) {
                                            System.out.println("Word '" + wordToSearch
                                                            + "' found at "
                                                            + counter
                                                            + " in "
                                                            + fileNameToSearch);
                                    }
                            }
                    } else {
                            System.out.println(fileNameToSearch
                                            + " is not readable.");
                    }

            } catch (IOException x) {
                System.err.format("IOException: %s%n", x);
            }

    }
4

2 回答 2

4

您在此处继续重用的此 Search 实例:

search.setFileNameToSearch(file);
executor.submit(search);

虽然它的实际 search() 方法是同步的,但当它实际开始搜索某些东西时,它似乎setFileNameToSearch()已经被调用了多次,这可以解释跳过的原因。

Search每次创建一个新实例,然后您不需要同步实际search()功能。

于 2013-07-23T19:51:17.740 回答
2

您正在创建方法ExecutorService内部listFiles,这可能不是一个好主意:因此您可能创建了太多线程。

最重要的是,您没有监视所有这些的状态,ExecutorServices当您的应用程序停止时,其中一些可能不会启动

相反,您应该ExecutorService在开始递归之前创建唯一一次。递归结束后,调用shutdown()ExecutorService 等待所有任务完成

此外,您正在重用一个Search对象并将其传递给多个任务,同时修改它,您应该为您正在处理的每个文件创建一个搜索

于 2013-07-23T19:53:52.490 回答