1

我正在开发一个将数字计算为幂的 Java 应用程序。我想利用我的四核计算机,因为这个应用程序只使用了一个内核。我看过关于如何同步线程的不同教程,但我真的不明白。我的代码如下:

public class Bignum{

public static void main(String[] args){

    Random generator = new Random();   
    long start = System.nanoTime();   
    Random generator1 = new Random();

for (long i=0; i<9000;i++){

    int power = generator1.nextInt (17) + 2;
    int power1 = generator1.nextInt (25) + 2;
    int power2 = generator1.nextInt (72) + 2;

    BigInteger num = BigInteger.valueOf (generator.nextInt (7895) + 1);
    BigInteger num1 = BigInteger.valueOf (generator.nextInt (1250) + 1);
    BigInteger num2 = BigInteger.valueOf (generator.nextInt (9765) + 1);

    BigInteger add = num.pow(power);
    BigInteger add1 = num1.pow(power1);
    BigInteger add2 = num2.pow(power2);

    BigInteger sum = add.add(add1);

}

}
}

因此,例如,我怎么能让一个线程这样做:

    int power = generator1.nextInt (17) + 2;
    int power1 = generator1.nextInt (25) + 2;
    int power2 = generator1.nextInt (72) + 2;

另一个这样做:

    BigInteger num = BigInteger.valueOf (generator.nextInt (7895) + 1);
    BigInteger num1 = BigInteger.valueOf (generator.nextInt (1250) + 1);
    BigInteger num2 = BigInteger.valueOf (generator.nextInt (9765) + 1);

另一个这个:

    BigInteger add = num.pow(power);
    BigInteger add1 = num1.pow(power1);
    BigInteger add2 = num2.pow(power2);

最后一个这样做:

    BigInteger sum = add.add(add1);

我怎么能那样做?另外,我怎么还能重复9000次?谢谢您的帮助。

4

3 回答 3

3

在 Java 8 中,并行数学可以非常优雅。下面的代码利用了“+”操作是加法的这一事实,因此可以按任何顺序对值求和。

因此,下面的代码并行创建一个数字序列,并在单个线程中减少(求和)它们。

import java.math.BigInteger;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.IntStream;

import static java.math.BigInteger.valueOf;
import static java.util.concurrent.ThreadLocalRandom.current;

public class Bignum {
    public static void main(String[] args) {
        Optional<BigInteger> sum = IntStream.range(0, 9000)
            .parallel()       <-- this enables parallel execution
            .mapToObj(value -> {
                ThreadLocalRandom generator = current();

                int power = generator.nextInt(17) + 2;
                int power1 = generator.nextInt(25) + 2;
                int power2 = generator.nextInt(72) + 2;

                BigInteger num = valueOf(generator.nextInt(7895) + 1);
                BigInteger num1 = valueOf(generator.nextInt(1250) + 1);
                BigInteger num2 = valueOf(generator.nextInt(9765) + 1);

                BigInteger add = num.pow(power);
                BigInteger add1 = num1.pow(power1);
                BigInteger add2 = num2.pow(power2);

                return add.add(add1).add(add2);
            })
            .reduce(BigInteger::add);

        System.out.println(sum.get());
    }
}
于 2013-11-14T22:03:04.847 回答
2

所以我真的推荐这本书来开始使用java多线程。这就像这东西的圣经。

话虽如此,您将需要一个线程池来保存您的任务,并且您将需要创建一个“工人”类(它将成为线程)来处理它需要做的事情,并正确退出/返回它的价值。

- 制作你的线程池

ExecutorService executor = Executors.newFixedThreadPool(MAX_NUMBER_THREADS_AT_ONCE);

-让你的工人任务

public static class WorkerTask implements Runnable {
    //member vars if you need em

    WorkerTask() {
        //initialize member vars if you need to
    }

    @Override
    public void run() {
            //do your work here 
    }
}

- 像这样向线程池添加任务:

for( each task you need ){
        Runnable worker = new WorkerTask( constructor params );
        executor.execute(worker);
    }

最后,这留下了两个问题:

我如何等待他们完成?

如何从线程返回值?

事实是,这两个问题都有很多解决方法,这些方法可能特定于您的问题,但我认为在这种情况下,您可以做一些简单的事情。我推荐一个全局静态变量,它具有全局范围并且能够被所有线程访问。这里要小心,不要编辑与其他线程相同的值,所以使用 ConcurrentHashMap 之类的东西,当线程有答案时,只需将线程 id 及其答案添加到 hashmap 即可。例如:concurrentMap.add(threadId, value);

要等到所有任务完成,我通常会这样做:

executor.shutdown();  //signal that you want to shutdown executor
while(!executor.isTerminated()){
        Thread.sleep(10000);  //wait ten seconds
        System.out.println("Waiting 10 seconds");
}
// now finally traverse your value map and output your answers
于 2013-11-14T21:43:21.817 回答
1

我更喜欢使用队列进行线程输入和输出,只需查看文档中的示例:http: //download.java.net/jdk7/archive/b123/docs/api/java/util/concurrent/BlockingQueue.html

一般来说,使用线程有 2.5 个原因:

  1. 在多 CPU 系统中
  2. 处理 IO 时(显示器、鼠标、键盘、套接字、读/写文件等)
  3. 用于计时器

假设你没有做 IO 并且不需要计时器,拥有比你的系统 CPU 更多的线程会减慢你的速度

于 2013-11-14T21:59:27.220 回答