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.setFileNameToSearch(file);
executor.submit(search);

実際の search() メソッドは同期されていますが、実際に検索を開始するまでに、何かsetFileNameToSearch()が数回呼び出されたように見えます。これにより、スキップが説明されます。

Search毎回新しいインスタンスを作成すると、実際のsearch()関数を同期する必要がなくなります。

于 2013-07-23T19:51:17.740 に答える