简体   繁体   English

如何将Math工作拆分为工作线程Java

[英]How to split Math work into worker threads Java

I'm developing a Java app that calcuates numbers to powers. 我正在开发一个Java应用程序,可以计算幂次。 I would like to take advantage of my quad core computer, as only one core is being used with this application. 我想利用我的四核计算机,因为此应用程序仅使用一个核。 I've looked at different tutorials on how to syncronize threads, but I don't really get it. 我看过有关如何同步线程的不同教程,但我确实不明白。 My code is below: 我的代码如下:

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);

}

}
}

So, for example, how could I have one thread do this: 因此,例如,如何让一个线程执行此操作:

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

Another do this: 另一个这样做:

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

Another this: 另一个:

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

And the last one do this: 最后一个是这样做的:

    BigInteger sum = add.add(add1);

How could I do that? 我该怎么办? Also, how could I still repeat that 9000 times? 另外,我怎么还能重复9000次? Thank you for your help. 谢谢您的帮助。

In Java 8 parallel maths can be quite elegant. 在Java 8中,并行数学可能非常优雅。 Code below takes advantage of the fact that "+" operation is additive, so values can be summed in any order. 下面的代码利用了“ +”运算是加法运算的事实,因此可以按任意顺序对值进行求和。

So the code below create a sequence of numbers in parallel and reduces (sums) them in a single thread. 因此,下面的代码并行创建一个数字序列,并在单个线程中减少(加和)它们。

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());
    }
}

So i really recommend this book to get started with java multi-threading. 因此,我真的推荐这本书开始使用Java多线程。 It's like the bible of this stuff. 就像这本书的圣经。

That being said, you're going to need a thread pool to hold your tasks, and youre going to need to make a 'worker' class (which will become the thread) that handles what it needs to do, and properly exits/returns its value. 话虽这么说,您将需要一个线程池来保存您的任务,并且您需要创建一个“工人”类(将成为线程)来处理需要执行的操作,并正确地退出/返回它的价值。

-Make your thread pool -使您的线程池

ExecutorService executor = Executors.newFixedThreadPool(MAX_NUMBER_THREADS_AT_ONCE);

-Make your worker task -完成您的工作任务

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 
    }
}

-Add tasks to the thread pool like this: -将任务添加到线程池中,如下所示:

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

Finally, this leaves two questions: 最后,这留下两个问题:

How do I wait for them to finish? 我要如何等待他们完成?

How do I return a value from a thread? 如何从线程返回值?

The fact is that both of these questions have a bunch of ways to solve which might be specific to your problem, but I think in this case you can do something simple. 事实是,这两个问题都有很多方法可以解决您的问题,但是我认为在这种情况下,您可以做一些简单的事情。 I recommend a global static class variable which will have global scope and be able to be accessed by all threads. 我建议使用一个全局静态变量,该变量将具有全局作用域,并且可以被所有线程访问。 Be careful here, dont edit the same values as other threads, so use something like a ConcurrentHashMap, and when a thread has its answer, just add the thread id and its answer to the hashmap. 在这里要小心,不要编辑与其他线程相同的值,因此请使用类似ConcurrentHashMap的名称,并且当一个线程有了答案时,只需将线程ID及其答案添加到哈希图中即可。 ex: concurrentMap.add(threadId, value); 例如:parallelMap.add(threadId,value);

To wait until all the tasks are done I usually do something like this: 为了等待所有任务完成,我通常会执行以下操作:

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

I prefer working with queues for thread input and output, just see the example in the docs: http://download.java.net/jdk7/archive/b123/docs/api/java/util/concurrent/BlockingQueue.html 我更喜欢使用队列进行线程输入和输出,请参阅文档中的示例: http : //download.java.net/jdk7/archive/b123/docs/api/java/util/concurrent/BlockingQueue.html

In general there are 2.5 reasons for using threads to begin with: 通常,有2.5个使用线程开头的原因:

  1. In multi cpu systems 在多CP​​U系统中
  2. when dealing with IO (monitor, mouse, keyboard, sockets, read / write files etc.) 处理IO(监视器,鼠标,键盘,套接字,读/写文件等)时
  3. for timers 计时器

Assuming you are not doing IO and not need timers, having more threads than your system CPU is going to slow you dowwwwwwwwwwwn 假设您不执行IO且不需要计时器,那么线程数多于系统CPU的速度将降低您的速度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM