我正在用Java测试并发性,我的目标是确定拥有多个线程是否实际上是有益的,但是,我得到的结果并没有加总。我正在尝试优化阶乘函数,对于此特定测试,我正在使用1e9!我想要模1e9 + 7的结果,以免溢出。首先,我根据number_of_threads划分数字,并分别为每个线程分配其工作。然后,我通常会这样做并比较我得到的时间。看来,当number_of_threads = 4时,与没有线程的版本相比,我得到的结果更好,这是有道理的,因为我的CPU有4个内核。不出所料,大于4的任何线程数的时间都比仅4的慢。但是,当线程数少于4时,结果变得很大,例如,对于1个线程,我希望它的持续时间与执行相同它没有线程+开销。没有线程,我只有1个线程的时间是6.2秒和19.3,这对它来说仅仅是开销而已。
为了测试原因,我在run方法上添加了一个计数器,有时似乎只执行一次for的内部周期要花费一毫秒多的时间,因此不应该这样做,因为它只是两个操作加上计时器。
public class Calc implements Runnable{ long min, max, mod, res; Res r; public Calc(long min, long max, long mod, Res r) { this.min = min; this.max = max; this.mod = mod; res = 1; this.r = r; } public void run() { for(long i = min; i <= max; i++) { res *= i; res %= mod; } r.addup(res); } } public class Res{ long result; long mod; public Res(long mod) { result = 1; this.mod = mod; } public synchronized void addup(long add) { result *= add; result %= mod; } public long getResult() { return result; } } public class Main{ public static void main(String args[]) { long startTime = System.nanoTime(); final long factorial = 1000000000L; final long modulo = 1000000007L; Res res = new Res(modulo); int number_of_threads = 1; Thread[] c = new Thread[number_of_threads]; long min = 1, max = factorial/(long)number_of_threads; long cant = max; for(int i = 0; i < number_of_threads; i++) { if((long)i < (factorial % number_of_threads))max++; c[i] = new Thread(new Calc(min, max, modulo, res)); c[i].start(); min = max +1; max += cant; } for(int i = 0; i < number_of_threads; i++) { try { c[i].join(); }catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(res.getResult()); long endTime = System.nanoTime(); long totalTime = endTime - startTime; System.out.println((double)totalTime/1000000000L); } }
[number_of_threads = 1时,我得到19.3秒。当number_of_threads = 2时,我得到10.1秒。当number_of_threads = 3时,我得到7.1秒。当number_of_threads = 4时,我得到5.4秒。当没有线程时,我得到6.2秒(我用相同的方法计算出这个时间)
只有1个线程和没有线程之间应该没有太大的区别,对于2和3个线程,它应该比没有线程快。为什么会这样,有什么办法可以解决?谢谢。
编辑:添加无线程版本
public class Main{
public static void main(String args[]) {
long startTime = System.nanoTime();
final long factorial = 1000000000L;
final long modulo = 1000000007L;
long res = 1;
for(long i = 1; i <= factorial; i++) {
res *= i;
res %= modulo;
}
System.out.println(res);
long endTime = System.nanoTime();
long totalTime = endTime - startTime;
System.out.println((double)totalTime/1000000000L);
}
}
我正在用Java测试并发性,我的目标是确定拥有多个线程是否实际上是有益的,但是,我得到的结果并没有加总。我正在尝试优化阶乘...
这是因为您的“无线程”(仅主线程)版本使用所有易于优化的编译时常量。