Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java parallel()的并发问题_Java_Concurrency_Thread Safety_Java Stream_Spliterator - Fatal编程技术网

Java parallel()的并发问题

Java parallel()的并发问题,java,concurrency,thread-safety,java-stream,spliterator,Java,Concurrency,Thread Safety,Java Stream,Spliterator,我有一个问题,这段代码在每次运行时返回的值都不相同。我认为这是因为它不是线程安全的,并且我在使用parallel()时遇到了一些并发性问题。我曾尝试使用拆分器,这是可行的,但运行时性能差3倍,与sequental相同。我还能怎么做 附言: traverseDirectory返回目录中所有.txt文件的BlockingQueue try { pq = traverseDirectory(dir, pq); while(!pq.isEmpty()){ File f

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

附言: 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());
编辑
我忘了提到,我需要记录在哪一行找到了这个词

列表不能保证线程安全,因此当您写入单词列表时,并发写入列表可能会相互干扰,特别是当列表在结构上被修改以容纳附加值时。文档建议确保在这种情况下同步访问列表

最好用更多的流处理来替换
forEach
,以避免此类并发问题。不要使用forEach,请尝试以下操作

.flatMap(line -> Arrays.stream(line.split("\\s+")))
这将产生所有行中所有单词的流。然后,您可以使用
.count()
终止流以获取字数,或者使用
collect()
将它们添加到某种集合中

@霍尔格指出,通过反复使用
字符串
regex进行拆分,每次迭代都会重新编译相同的regex。改用

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

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

列表不能保证线程安全,因此当您写入word列表时,对列表的并发写入可能会相互干扰,特别是当列表在结构上被修改以容纳附加值时。文档建议确保在这种情况下同步访问列表

最好用更多的流处理来替换
forEach
,以避免此类并发问题。不要使用forEach,请尝试以下操作

.flatMap(line -> Arrays.stream(line.split("\\s+")))
这将产生所有行中所有单词的流。然后,您可以使用
.count()
终止流以获取字数,或者使用
collect()
将它们添加到某种集合中

@霍尔格指出,通过反复使用
字符串
regex进行拆分,每次迭代都会重新编译相同的regex。改用

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

<> >每个文件只编译一次。

正确,但是您可以考虑使用<代码> .FLAMP(模式:编译(“s++”)::SPLITASFROW)< /COD>。它确保正则表达式模式只解析一次而不是每行,并且不会为每行填充中间数组。@Holger
splitAsStream
对我来说是一个新的。你让我开心了。@Holger flatMap到底做了什么?
splitAsStream
返回一个
,因此在
map()
中使用它将把你的
变成
流。使用
flatMap()!顺便说一句,我需要记录在哪一行找到这个词。这是非常重要的。正确,但是你可以考虑使用<代码> .Falm(模式:编译(“s++”)::SPLITASFISH)< /COD>。它确保正则表达式模式只解析一次而不是每行,并且不会为每行填充中间数组。@Holger
splitAsStream
对我来说是一个新的。你让我开心了。@Holger flatMap到底做了什么?
splitAsStream
返回一个
,因此在
map()
中使用它将把你的
变成
流。使用
flatMap()!顺便说一句,我需要记录在哪一行找到这个词。这是非常重要的。