我想通过并行计算它们来计算任意数量的所有素数。我知道isPrime()可以从现在改进,但主要问题是我无法同步对存储结果的ArrayList的访问。我已经实例化了一个虚拟对象“m”来充当监视器并控制对数组的访问。很明显,我在某处推理时犯了一个错误,因为每次都得到java.util.ConcurrentModificationException。 NB:gist同步访问ArrayList
编辑:更新后显示完成建议。
import java.util.ArrayList;
public class Main {
static final int MAX = 100000000;
static final int THREADS = Runtime.getRuntime().availableProcessors();
static final int ARRINITSIZE = 100000;
static ArrayList<Integer> primes = new ArrayList<Integer>(ARRINITSIZE);
public static void main(String[] args) {
Thread[] t = new Thread[THREADS];
PrimeRun.m = new Monitor();
for (int i=0; i<THREADS; i++) {
t[i] = new Thread(new PrimeRun(i));
t[i].start();
}
// wait for threads to finish
for (int i=0; i<THREADS; i++)
t[i].join();
// NOTE: primes will be out of order because of random thread scheduling
for (int n : primes)
System.out.print("" + n + " ");
System.out.println();
}
static boolean isPrime(int n) {
if (n == 2 || n == 3 || n == 5) return true;
if (n <= 1 || (n&1) == 0) return false;
for (int i = 3; i*i <= n; i += 2)
if (n % i == 0) return false;
return true;
}
synchronized static void addPrime(int n) {
primes.add(n);
}
}
class PrimeRun implements Runnable {
public static Monitor m;
final int ID;
public PrimeRun(int i) {
ID = i;
}
public void run() {
for(int i=0; i < Main.MAX; i++) {
if(i % Main.THREADS == ID)
if(Main.isPrime(i))
m.addPrime(i);
}
}
}
class Monitor {
public synchronized void addPrime(int n) {
Main.addPrime(n);
}
}
我包括我的ant脚本为了方便:)
<project default="cmp">
<target name="cmp"><javac srcdir="." debug="true"/></target>
<target name="run" depends="cmp"><java classname="Main" classpath="."/></target>
<target name="cln"><delete><fileset dir="." includes="*.class"/></delete></target>
</project>
要评论你的'isPrime()'方法而不是除以i + = 2,请尝试除以primes.get(i ++)。这会让你在通过3和5之后再除以15。 – gobernador 2012-07-28 06:13:54
@gobernador您的意思是,读取已经计算并以该数字为模的质数的数组?或者你的意思是增加一个不同的值的循环计数器? – xst 2012-07-28 06:18:00
通过素数低于您测试的数量来模数。这将导致更少的计算,并在质数更少的较高数字上为您提供极大的速度提升。 – gobernador 2012-07-28 18:46:41