Java中的线程因子性能

时间:2017-05-02 18:13:32

标签: java multithreading factorial

我在stackoverflow上搜索Java中的多线程factorial变体,但令我惊讶的是,没有任何。所以我想自己做,因为我希望看到性能有所提高。 (我在这里为正在搜索此内容的人分享代码。) 现在我想将其性能与单线程迭代方法和递归方法进行比较。但我没有看到任何性能提升,它的单线程对应物的价值高达1200! (长数据类型不能保持21的值!因为它大于Long.MAX_VALUE。)那么如何使用更大的数字进行比较?我正在使用BigInteger和1232!是两种方法得到的最大值。

import java.math.BigInteger;
import java.util.Arrays;

public class MultiThreadedFactorial
{
    public static void main(String[] args) throws InterruptedException
    {
        long startTime=System.nanoTime();

        int x=1232;

        if(x<2) return;

        int[] array=new int[x-1];//It is x-1 because of 1 is not included in 2...10.
        for(int i=0;i<array.length;i++)
        {
            array[i]=i+2;
        }

        int[] partA=Arrays.copyOfRange(array,0,array.length/3);//Dividing array into 3 equal parts
        PartialProduct A=new PartialProduct(partA);

        int[] partB=Arrays.copyOfRange(array,array.length/3,2*array.length/3);
        PartialProduct B=new PartialProduct(partB); 

        int[] partC=Arrays.copyOfRange(array,2*array.length/3,array.length);
        PartialProduct C=new PartialProduct(partC);

        A.start();
        B.start();
        C.start();

        A.join();
        B.join();
        C.join();

        BigInteger bi=new BigInteger(A.product+"");
        bi=bi.multiply(new BigInteger(B.product+""));
        bi=bi.multiply(new BigInteger(C.product+""));

        System.out.println(bi.toString());

        long endTime=System.nanoTime();
        float totalTime=(endTime-startTime)/1000000000f;
        System.out.println("Took "+totalTime+" seconds!");
    }

    static long multiply(long... numbers)
    {
        long factorial=1;
        for(long n:numbers)
            factorial*=n;
        return factorial;
    }

}

class PartialProduct extends Thread
{
    int[] numbers;
    BigInteger product=new BigInteger("1");

    public PartialProduct(int[] numbers)
    {
        this.numbers=numbers;
    }

    public void run()
    {
        for(int n:numbers)
            product=product.multiply(BigInteger.valueOf(n));
    }
}

1 个答案:

答案 0 :(得分:1)

使用Java 8中提供的Java流API编写factorial的并行版本要容易得多。

单线程实现可能如下所示:

  static BigInteger sequentialFactorial(int n)
  {
    if (n < 2)
      return BigInteger.ONE;
    return IntStream.rangeClosed(2, n)
        .sequential()
        .mapToObj(BigInteger::valueOf)
        .reduce(BigInteger.ONE, BigInteger::multiply, BigInteger::multiply);
  }

并行/多线程版本是一个微不足道的变化:

  static BigInteger parallelFactorial(int n)
  {
    if (n < 2)
      return BigInteger.ONE;
    return IntStream.rangeClosed(2, n)
        .parallel()
        .mapToObj(BigInteger::valueOf)
        .reduce(BigInteger.ONE, BigInteger::multiply, BigInteger::multiply);
  }

如果你以明智的方式计算时间(例如,1000次迭代,每次计算1000次!),你应该会在多核机器上看到显着的加速。