我正在开发一个计算数字到幂的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次呢?谢谢你的帮助。
在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());
}
}
所以我真的推荐这本书来开始使用Java多线程。 这就像这些东西的圣经。
话虽如此,你将需要一个线程池来保存你的任务,你将需要创建一个"worker"类(它将成为线程)来处理它需要做的事情,并正确退出/返回它的值。
-制作你的线程池
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 及其答案添加到哈希映射中即可。 例如: 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
我更喜欢使用队列进行线程输入和输出,只需查看文档中的示例:http://download.java.net/jdk7/archive/b123/docs/api/java/util/concurrent/BlockingQueue.html
一般来说,首先使用线程有 2.5 个原因:
- 在多 CPU 系统中
- 处理IO(显示器,鼠标,键盘,套接字,读/写文件等)时
- 对于计时器
假设你没有做IO并且不需要计时器,拥有比系统CPU更多的线程会减慢你的速度wwwwwwn