程序功能说明:计算某个范围内的质数,分别用单线程和多线程实现,比较计算时间。
抽象类AbstractPrimeFinder:计算质数的父类,isPrime(final int number)用来判断传入的int值是否是质数,countPrimesInRange(final int lower,final int upper)通过调用isPrime()方法计算某一范围内质数的数量,timeAndCompute()方法用来统计和输出计算质数花费的时间。
//抽象类AbstractPrimeFinder
abstract class AbstractPrimeFinder {
public boolean isPrime(final int number) {
if (number <= 1)
return false;
for (int i = 2; i <= Math.sqrt(number); i++)
if (number % i == 0)
return false;
return true;
}
public int countPrimesInRange(final int lower, final int upper) {
int total = 0;
for (int i = lower; i <= upper; i++)
if (isPrime(i))
total++;
return total;
}
public void timeAndCompute(final int number) {
final long start = System.nanoTime();
final long numberOfPrimes = countPrimes(number);
final long end = System.nanoTime();
System.out.printf("Number of primes under %d is %d\n", number,
numberOfPrimes);
System.out.println("Time (seconds) taken is " + (end - start) / 1.0e9);
}
public abstract int countPrimes(final int number);
}
/**
*单线程代码
*/
public class SequentialPrimeFinder extends AbstractPrimeFinder {
//重写父类的countPrimes方法
public int countPrimes(final int number) {
return countPrimesInRange(1, number);
}
public static void main(final String[] args) {
//调用timeAndCompute方法,输出1千万以内的质数和计算用时
new SequentialPrimeFinder().timeAndCompute(10000000);
}
}
/*单线程下的执行结果
Number of primes under 10000000 is 664579
Time (seconds) taken is 7.518444261
*/
双线程代码
package com.mime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class ConcurrentPrimeFinder extends AbstractPrimeFinder {
//定义每个线程计算范围内的数字的数量
private final int poolSize;
//定义线程数量
private final int numberOfParts;
//线程构造方法,根据起始点和计算数量
public ConcurrentPrimeFinder(final int thePoolSize,
final int theNumberOfParts) {
poolSize = thePoolSize;
numberOfParts = theNumberOfParts;
}
//重写countPrimes方法
public int countPrimes(final int number) {
int count = 0;
try {
final List<Callable<Integer>> partitions = new ArrayList<Callable<Integer>>();
final int chunksPerPartition = number / numberOfParts;
for (int i = 0; i < numberOfParts; i++) {
final int lower = (i * chunksPerPartition) + 1;
final int upper = (i == numberOfParts - 1) ? number : lower
+ chunksPerPartition - 1;
partitions.add(new Callable<Integer>() {
public Integer call() {
return countPrimesInRange(lower, upper);
}
});
}
final ExecutorService executorPool = Executors
.newFixedThreadPool(poolSize);
final List<Future<Integer>> resultFromParts = executorPool
.invokeAll(partitions, 10000, TimeUnit.SECONDS);
executorPool.shutdown();
for (final Future<Integer> result : resultFromParts)
count += result.get();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return count;
}
//测试结果
public static void main(final String[] args) {
//调用timeAndCompute方法,输出1千万以内的质数和计算用时
new ConcurrentPrimeFinder(4,100).timeAndCompute(10000000);
}
}
输出
Number of primes under 10000000 is 664579
Time (seconds) taken is 3.825282456
可以根据cpu个数和调整分区树来调优这个线程数来达到最有效果。