当前位置: 首页 > 知识库问答 >
问题:

减少没有组合器的并行流由多个线程正确执行。在这种情况下,我应该什么时候使用组合器?

易星纬
2023-03-14

我阅读了以下内容:

https://stackoverflow.com/a/22814174/2674303

我决定合并器只在并行流中使用,以获得正确的合并累加器结果。每个线程上有一个累加器实例。

因此,我作出决议,减少没有合路器将无法正常工作。

为了验证这一点,我编写了以下示例:

   Person reduce = Person.getPersons().stream()
                .parallel() 
                .reduce(new Person(), (intermediateResult, p2) -> {
                    System.out.println(Thread.currentThread().getName());
                    return new Person("default", intermediateResult.getAge() + p2.getAge());
                });
        System.out.println(reduce);

型号:

public class Person {

    String name;

    Integer age;
    ///...

    public static Collection<Person> getPersons() {
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("Vasya", 12));
        persons.add(new Person("Petya", 32));
        persons.add(new Person("Serj", 10));
        persons.add(new Person("Onotole", 18));
        return persons;
   }
}

如您所见,我不提供组合器
示例输出:

ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-1
ForkJoinPool.commonPool-worker-1
Person{name='default', age=72}

我已经执行了几次应用程序,总是看到正确的结果。

请解释一下,如果不提供合并器,如何减少并行流的工作。

共有3个答案

师野
2023-03-14

3-argumentreduce适用于以下不常见的情况:

想象一下,不是将人流减少为人流,而是使用不同的中间值,如PopulationStats。

class PopulationStats {
  // make new stats that includes this person
  PopulationStats addPerson(Person p) {
    return new PopulationStats(........);
  }

  // make new stats that combines this and other stats
  PopulationStats addStats(PopulationStats other) {
    return new PopulationStats(........);
  } 
}

在这种情况下,3参数减少用于避免在减少之前为每个Person制作PopulationStats的中间步骤。

PopulationStats stats = people.stream()
  .reduce(new PopulationStats(), PopulationStats::addPerson, PopulationStats::addStats);

郭思聪
2023-03-14

您指定了一个组合器。在这种情况下,合并器函数与累加器函数相同。

如果结果类型与流元素类型相同,那么这总是可能的。

与通过求和值进行约简相比,a b c d可以通过计算(a b)(c d)并行计算。这里,累加器是加法,它与处理(a b)(c d)中间结果的组合器函数的操作相同。

该示例还表明,除非涉及类型转换,否则如果需要不同的组合器函数,则会很奇怪,因为累加器函数的关联性约束意味着它通常足以作为组合器函数。请记住,流是否计算、a b c d(a b c)d(a b)(c d)a(b c d)应该是无关的。

颜君浩
2023-03-14

在这种情况下,累加器也可以作为合路器工作。当归约类型与流元素类型相同时,这是一种简写。因此

myStream.reduce(identity, accumulator);

完全等同于

myStream.reduce(identity, accumulator, accumulator);

您甚至可以在OpenJDK中查看这些方法的源代码:

@Override
public final <R> R reduce(R identity, BiFunction<R, ? super P_OUT, R> accumulator, 
                          BinaryOperator<R> combiner) {
    return evaluate(ReduceOps.makeRef(identity, accumulator, combiner));
}

@Override
public final P_OUT reduce(final P_OUT identity, final BinaryOperator<P_OUT> accumulator) {
    return evaluate(ReduceOps.makeRef(identity, accumulator, accumulator));
}

三参数版本更灵活,因为归约操作可能会生成另一种类型的对象。在这种情况下,您不能使用双参数归约,因为您没有提供如何组合结果类型的两个元素的规则。然而,当结果类型相同时,累加器和合并器处理相同的对象类型,因此如果它是关联的,则应该是相同的操作。

 类似资料:
  • 我正在阅读mapreduce with combiners教程http://www . tutorialspoint . com/map _ reduce/map _ reduce _ combiners . htm 减速器从组合器接收以下输入: 我的疑问是,如果我跳过组合器并允许映射器将输出传递给减速器而不执行任何分组操作(不使用组合器)并允许它通过洗牌和排序阶段会怎样。 在映射器阶段结束并经过

  • 我使用的API接受单个AKKA接收器,并用数据填充: 有没有一种方法,在不深入阿卡的深度的情况下,用两个汇而不是一个汇来处理输出? 例如 如果我可以访问方法使用的Flow,我可以使用,但流不会公开。 目前唯一的解决方法是将一个处理字符串的水槽传递给两个StringBuilder,以替换,但这似乎违背了AKKA的观点。如果不花几天时间学习AKKA,我就不知道是否有办法将输出从接收器中分离出来。 谢谢

  • 我必须编写spark streaming(createDirectStream API)代码。我将接收大约90K消息每秒,所以虽然使用100个分区为Kafka主题,以提高性能。 能不能请你告诉我,我该用多少个遗嘱执行人?我可以使用50个执行器和每个执行器2个核心吗? 另外,考虑如果批处理间隔为10秒,并且kafka主题的分区数为100,我会从每个kafka分区接收100个RDD,即1个RDD吗?在

  • 使用Java 8和lambdas可以很容易地将集合作为流进行迭代,使用并行流也同样容易。文档中的两个示例,第二个使用ParallelStream: 只要我不关心顺序,使用平行会一直是有益的吗?人们会认为在更多的核心上分配工作是更快的。 还有其他考虑吗?什么时候应该使用并行流,什么时候应该使用非并行流? (问这个问题是为了引发关于如何以及何时使用并行流的讨论,而不是因为我认为始终使用它们是一个好主意

  • 问题内容: 我正在寻找没有浏览器的Javascript编程。我想从Linux或MacOSX命令行运行脚本,就像我们运行任何其他脚本语言(ruby,PHP,Perl,Python …)一样 我研究了spider monkey(Mozilla)和v8(Google),但它们似乎都是嵌入式的。 是否有人将Javascript作为脚本语言从命令行执行? 如果有人好奇,为什么我期待到这一点,我一直在关注着N

  • 我刚刚在使用及其方法时遇到了一个问题。虽然我知道如何使用它们,但我不太确定何时使用它们。 例如,我有一个列表,包含到不同位置的各种路径。现在,我想检查一个给定的路径是否包含列表中指定的任何路径。我想根据是否满足条件返回。 当然,这本身并不是一项艰巨的任务。但是我想知道我是应该使用流还是使用for(-each)循环。 列表 示例-流 示例For-Each循环 请注意,参数始终是小写的。 我的第一个猜