0

我有一个问题,该代码每次运行时都不会返回相同的值。我认为这是因为它不是线程安全的,并且我在使用 parallel() 时遇到了一些并发问题。我曾尝试使用分离器,这很有效,但运行时因为差 3 倍,与顺序相同。我还能怎么做?

ps:traverseDirectory返回一个目录下所有.txt文件的BlockingQueue。

try {
    pq = traverseDirectory(dir, pq);

    while(!pq.isEmpty()){

        File f = pq.take();
        LineNumberReader lr = new LineNumberReader(new FileReader(f));
        lr.lines()
            .parallel()
            .forEach((line) -> {
                String[] words = line.split("\\s+");
                for( String word : words ){
                    wordList.add(word);
                }

             }); // foreach

     } // while

} //try
catch (IOException | InterruptedException e) {}

System.out.println("size: " + wordList.size());

编辑 我忘了提到,我需要跟踪在哪一行找到了这个词!

4

1 回答 1

2

列表不能保证是线程安全的,因此当您写入单词列表时,并发写入列表可能会相互干扰,尤其是在对列表进行结构修改以适应附加值时。文档建议确保在这种情况下同步访问列表。

您最好forEach用更多的流处理替换 以避免此类并发问题。而不是forEach,尝试类似

.flatMap(line -> Arrays.stream(line.split("\\s+")))

这将产生所有行中所有单词的流。然后,您可以终止流.count()以获取单词数,或者collect()将它们转换为某种集合。

@Holger 指出,通过使用String正则表达式反复拆分,每次迭代都会重新编译相同的正则表达式。通过使用

.flatMap(Pattern.compile("\\s+")::splitAsStream)

正则表达式每个文件只编译一次。

于 2016-04-18T04:06:10.460 回答