写了一个多小时,调试了一晚上,应该没有问题了,支持大于等于2的所有long型数的判断,线程数选择要合理,小于int最大值的数一个线程就够了,多了没有帮助,超大的数也不要多于你的CPU核心数,不然反倒会更慢。public class MultiThreadedIsPrime { public static void main(String[] args) { testWithASingleNumber();
findPrimeNumbers(); }
public static void findPrimeNumbers() { int count = 0, threads = 2; long from = 5000, to = 10000;
for (long i = from; i <= to; i++) { if (isPrime(i, threads)) { count++; } }
System.out.println("There are " + count + " prime numbers on the interval [" + from + "," + to + "]"); }
public static void testWithASingleNumber() { long num = 9223372036854775783L; int threads = 2;
System.out.println("Checking if " + num + " is a prime number.");
long time = System.currentTimeMillis(); if (isPrime(num, threads)) { System.out.println(num + " is a prime number."); } else { System.out.println(num + " is not a prime number."); } time = System.currentTimeMillis() - time; System.out.println("Time consumed: " + time); }
public static boolean isPrime(long n, int threads) { if (threads <= 0) { throw new IllegalArgumentException("Illegal number of threads."); } if (n <= 1) { throw new IllegalArgumentException("Illegal number."); }
if (n <= 3 || n == 5 || n == 7) return true; if ((n & 1) == 0 || n % 3 == 0 || n % 5 == 0) return false;
long sqrt = (long)Math.sqrt(n) + 1; long interval = (((sqrt - 7) / 30 + 1) / threads) * 30;
if (interval == 0) { throw new IllegalArgumentException("Too many threads."); }
IntervalChecker[] checkers = new IntervalChecker[threads]; SharedMark = new SharedMark(threads);
if (threads == 1) { checkers[0] = new IntervalChecker(n, 7, sqrt, ); } else { checkers[0] = new IntervalChecker(n, 7, interval + 1, ); for (int i = 1; i < threads - 1; i++) { checkers[i] = new IntervalChecker(n, interval * i + 7, interval * (i + 1) + 1, ); } checkers[threads - 1] = new IntervalChecker(n, interval + 7, sqrt, ); }
for (int i = 0; i < threads; i++) { new Thread(checkers[i]).start(); }
计算机是一门实践科学,所以,我们一般都是比较务实的人。 楼主的这个问题,就经验而谈,没有实际意义。 多线程技术的应用场景,主要就两个方面:一、CPU密集型运算;二、异步阻塞处理。 楼主求一个数是否是素数,说实话,真没必要多线程。耗时时间长,占用内存多,编程复杂度相对要大。既然楼主是为了学习而学习,那么,我也只能用笨办法来解决了。 import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class PrimeUtil { public static final int QUEUE_SIZE = 100; private static final Operand POISON = new Operand(); private BlockingQueue<Operand> operands = new LinkedBlockingQueue<PrimeUtil.Operand>(QUEUE_SIZE); private BlockingQueue<Operand> results = new LinkedBlockingQueue<PrimeUtil.Operand>(QUEUE_SIZE); private boolean running = false; private long number;
public PrimeUtil(long number) { this.number = number; } static class Operand{ long dividend; //被除数 long divisor; //除数 long remainder; //余数 }
class Producer extends Thread{ public void run(){ try { for(int i=2;running && i<number;i++){ Operand o = new Operand(); o.dividend = number; o.divisor = i; operands.put(o); } operands.put(POISON); } catch (InterruptedException e) { } } }
然后各个线程运行指定区间的X%n,如果全部线程都不能整除,则是素数,返回主线程由主线程查看判断结果
public static void main(String[] args) {
testWithASingleNumber();
findPrimeNumbers();
}
public static void findPrimeNumbers() {
int count = 0, threads = 2;
long from = 5000, to = 10000;
for (long i = from; i <= to; i++) {
if (isPrime(i, threads)) {
count++;
}
}
System.out.println("There are " + count +
" prime numbers on the interval [" + from +
"," + to + "]");
}
public static void testWithASingleNumber() {
long num = 9223372036854775783L;
int threads = 2;
System.out.println("Checking if " + num + " is a prime number.");
long time = System.currentTimeMillis();
if (isPrime(num, threads)) {
System.out.println(num + " is a prime number.");
} else {
System.out.println(num + " is not a prime number.");
}
time = System.currentTimeMillis() - time;
System.out.println("Time consumed: " + time);
}
public static boolean isPrime(long n, int threads) {
if (threads <= 0) {
throw new IllegalArgumentException("Illegal number of threads.");
}
if (n <= 1) {
throw new IllegalArgumentException("Illegal number.");
}
if (n <= 3 || n == 5 || n == 7) return true;
if ((n & 1) == 0 || n % 3 == 0 || n % 5 == 0) return false;
long sqrt = (long)Math.sqrt(n) + 1;
long interval = (((sqrt - 7) / 30 + 1) / threads) * 30;
if (interval == 0) {
throw new IllegalArgumentException("Too many threads.");
}
IntervalChecker[] checkers = new IntervalChecker[threads];
SharedMark = new SharedMark(threads);
if (threads == 1) {
checkers[0] = new IntervalChecker(n, 7, sqrt, );
} else {
checkers[0] = new IntervalChecker(n, 7, interval + 1, );
for (int i = 1; i < threads - 1; i++) {
checkers[i] = new IntervalChecker(n, interval * i + 7,
interval * (i + 1) + 1, );
}
checkers[threads - 1] = new IntervalChecker(n, interval + 7, sqrt, );
}
for (int i = 0; i < threads; i++) {
new Thread(checkers[i]).start();
}
synchronized (.lock) {
do {
try {
.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (.runningThreads > 0);
}
return .unknown;
}
static class IntervalChecker implements Runnable {
long n, from, to;
final SharedMark ;
IntervalChecker(long n, long from, long to, SharedMark ) {
this.n = n;
this.from = from;
this.to = to;
this. = ;
}
@Override
public void run() {
final long[] steps = {4, 2, 4, 2, 4, 6, 2, 6};
int j = 0;
for (long i = from; .unknown && i <= to; i += steps[j &= 7], j++) {
if (n % i == 0) {
//System.out.println("Divisible by " + i);
.unknown = false;
break;
}
}
synchronized (.lock) {
.runningThreads--;
.lock.notify();
}
}
}
static class SharedMark {
boolean unknown;
final Object lock;
int runningThreads;
SharedMark(int threads) {
unknown = true;
lock = new Object();
runningThreads = threads;
}
}
}
楼主的这个问题,就经验而谈,没有实际意义。
多线程技术的应用场景,主要就两个方面:一、CPU密集型运算;二、异步阻塞处理。
楼主求一个数是否是素数,说实话,真没必要多线程。耗时时间长,占用内存多,编程复杂度相对要大。既然楼主是为了学习而学习,那么,我也只能用笨办法来解决了。
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class PrimeUtil { public static final int QUEUE_SIZE = 100;
private static final Operand POISON = new Operand();
private BlockingQueue<Operand> operands = new LinkedBlockingQueue<PrimeUtil.Operand>(QUEUE_SIZE);
private BlockingQueue<Operand> results = new LinkedBlockingQueue<PrimeUtil.Operand>(QUEUE_SIZE);
private boolean running = false;
private long number;
public PrimeUtil(long number) {
this.number = number;
} static class Operand{
long dividend; //被除数
long divisor; //除数
long remainder; //余数
}
class Producer extends Thread{
public void run(){
try {
for(int i=2;running && i<number;i++){
Operand o = new Operand();
o.dividend = number;
o.divisor = i;
operands.put(o);
}
operands.put(POISON);
} catch (InterruptedException e) {
}
}
}
class Consumer extends Thread{
public void run(){
try {
while(running){
Operand o = operands.take();
if(o==POISON){
operands.put(o);
results.put(o);
break;
}
o.remainder = o.dividend % o.divisor;
results.put(o);
}
} catch (InterruptedException e) {
}
}
}
private boolean isPrime(){
Producer producer = new Producer();
Consumer consumer = new Consumer();
running = true;
producer.start();
consumer.start();
try {
while(running){
Operand o = results.take();
if(o==POISON){
running = false;
return true;
}
if(o.remainder==0){
running = false;
}
}
} catch (InterruptedException e) {
}
return false;
}
public static boolean isPrime(long number){
if(number==1 || number==2)return true;
return new PrimeUtil(number).isPrime();
}
/**
* 测试用例
*/
public static void main(String[] args) {
System.out.println(isPrime(5));
}}