【问题标题】:Java 8 turn on parallel() stream with boolean? [closed]Java 8用布尔值打开parallel()流? [关闭]
【发布时间】:2016-01-06 17:37:07
【问题描述】:

我想知道如何设计可以同时运行或单线程运行的方法。例如我有一个这样的方法:

/**
 * Produces the norm of the two vector {@code v1}.
 * 
 * @param v1
 *            The first vector.
 * 
 * @param v2
 *            The second vector
 * 
 * @throws MathException
 *             Of type {@code DIMENSION_MISMATCH} if
 *             {@code v1.getDimension()} is != {@code v2.getDimension()}.
 */
public static Function<Vector, Double> norm = (v) -> {
    return Math.sqrt(
            IntStream.range(0, v.getDimension()).mapToDouble(i -> Math.pow(v.getEntry(i), 2)).sum());
};

如果我想让嵌入式流并行,那么我可以再次创建相同的方法并将parallel() 添加到流中,但这会增加很多样板。有parallel(boolean)开关可以用吗?

【问题讨论】:

  • 这仍然是在征求讨论和建议,最好这个词只是强调,取出它并不会改变仍然基于意见的基本问题,同时太宽泛。现在去掉best这个词只是混淆了这些问题。
  • @JarrodRoberson 出于好奇,您能想到多少种不同的实现方式?
  • 当然,在编程中通常有不同的方法来解决问题。这并不一定会使问题意见基于或过于广泛......
  • @JarrodRoberson 不一定。当有 2 个相同的解决方案只是以不同的方式编写时,意见就会发挥作用。如果不是,则有非自以为是的方式来比较它们的性能。你会诚实地在这里写一个 Spring 解决方案吗?因为您可以为每个可能的问题编写一个 Spring 解决方案。不,对于你是否想要这个没有意见:OP想要它。
  • (如果您考虑使用parallel() 来提高性能,您可能会发现unordered() 也可以提高性能。)

标签: java multithreading parallel-processing java-8 java-stream


【解决方案1】:

API 本身没有这样的开关,但您可以很容易地自己添加:

public static Function<Vector, Double> getNorm(boolean parallel) {
    return v -> {
        IntStream stream = IntStream.range(0, v.getDimension());
        stream = parallel ? stream.parallel() : stream;
        return Math.sqrt(stream.mapToDouble(i -> Math.pow(v.getEntry(i), 2)).sum());
    };
};

此代码仅根据布尔参数调用parallel() 或不调用。

【讨论】:

  • A BiFunction&lt;Vector, Boolean, Double&gt; 也可以放入其中(虽然它使用包装器类型,但很好......)。
  • 我不认为条件运算符在这里增加了可读性。一个普通的if(parallel) stream=stream.parallel(); 可以直接完成这项工作。
  • 我同意@Holger 但仍然非常简洁漂亮的解决方案!
  • 谢谢你们!这真的很甜!我正在考虑为 Matrix / Vector 模块添加并行功能,以试验算法中的并发性。您认为在函数级别进行烘焙是否有意义,或者我应该为此针对更大的代码块?
【解决方案2】:

只是想发布一个我认为 API 应该是什么样子的示例,以了解您的想法(我希望 Apache Commons Math 将在 4.0 中采用它,但同时该模块将在此处提供 firefly-math-linear-real ):

/**
 * Returns a {@link BiFunction} that multiplies the first vector {@code v1}
 * times the second vector {@code v2} .
 * 
 * Example {@code multiply().apply(v1, v2);}
 * 
 * @throws MathException
 *             Of type {@code DIMENSION_MISMATCH} if
 *             {@code v1.getDimension()} is != {@code v2.getDimension()}.
 */
public static BiFunction<Vector, Vector, Vector> multiply() {
    return VectorFunctions.multiply(false);
};

/**
 * Returns a {@link BiFunction} that multiplies the first vector {@code v1}
 * times the second vector {@code v2} .
 * 
 * Example {@code multiply(true).apply(v1, v2);}
 * 
 * @param parallel
 *            Whether to perform the multiplication in parallel.
 * 
 * @throws MathException
 *             Of type {@code DIMENSION_MISMATCH} if
 *             {@code v1.getDimension()} is != {@code v2.getDimension()}.
 */
public static BiFunction<Vector, Vector, Vector> multiply(boolean parallel) {
    return (v1, v2) -> {
        checkDimensionMismatch(v1, v2);
        IntStream stream = range(0, v1.getDimension());
        stream = parallel ? stream.parallel() : stream;
        return new Vector(stream.mapToDouble(i -> v1.getEntry(i)
                * v2.getEntry(i)).toArray());
    };
}

想法?

奥莱

【讨论】:

    【解决方案3】:

    创建两个函数

    一个名为 norm(如问题中提供的实现),另一个名为 parallelNorm。您可以在这些函数之间重用代码。

    让封装类控制并行性

    您的函数 norm 驻留在某个类中。我会

    • 使函数规范非静态
    • 在封装类中引入了名为 parallel 的最终布尔成员变量
    • 在构造函数中初始化并行成员变量
    • 函数 norm 将根据 parallel 成员变量的值使用并行或非并行流

    使用装饰器模式添加并行性

    就像上面的例子一样,我会使用非静态函数。 我会创建一个名为 Norm 的类(像上面那样实现 norm 函数)。 然后,我将创建类 ParallelNorm extends Norm,该类 @Override norm 具有并行实现的功能

    【讨论】:

    • 谢谢 - 我也喜欢你的想法。我想我可能会做 norm() 只返回非并行版本和 norm(boolean) 可以选择打开并行版本。
    猜你喜欢
    • 2012-09-29
    • 1970-01-01
    • 2016-12-06
    • 2018-08-28
    • 1970-01-01
    • 2014-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多