有一个线程计算素数并将其添加到集合中。
现在还有其他线程将执行bool isPrime(long n)
方法。如果该方法包含数字(n),则只会查看该集合。
但是执行isPrime(...)
的线程需要等到:
在这种情况下,它仅允许通知线程。因此,在将每个数字添加到集合后,我都无法通知并检查其数字是否更高。
您能在不忙于等待的情况下给我一些有关这种等待条件的解释吗?
我只知道我可以让线程在对象上等待,其他线程可以通知它们,但是我无法理解这种行为,也许我只是以错误的方式思考。
答案 0 :(得分:3)
这实际上取决于您的总体设计。
一个简单的解决方案将像这样工作:
wait()
wait()
。该解决方案的巨大优势:原始生成器不需要知道有多少个原始测试器。它只是通知所有在公用监视器上等待的线程。
或者,最初生成器可以确切知道存在哪些最初测试器,以及他们负责多少。因此,它不会唤醒所有测试人员,而只会通知需要知道的人员。
请理解:您仅给出了一些模糊的要求,没有任何代码。因此,您会收到一个含糊的答案,没有任何代码。我的回答是为了启发您指导下一步的作业。
仅作记录:如果您想获取非常大的质数,那么使用列表是一个不好的选择。假设您的清单包含100万个素数。调用contains()
的费用将随着条目数的增加而线性增加。因此,宁可使用可以快速查找元素(某种类型的集合/树)的集合,也可以快速访问集合中当前“最后一个”(最大)的数字。
答案 1 :(得分:0)
@GhostCat回答的基本思想变成了代码:
import java.util.HashSet;
import java.util.Set;
public class PrimeThreading {
// All prime numbers found so far.
private static final Set<Long> primes = new HashSet<>();
// Last number checked by the generator.
private static long numbersChecked = 0L;
// The lock object.
private static final Object lock = new Object();
private static class PrimeGenerator implements Runnable {
private final long maxNumber = Long.MAX_VALUE;
@Override
public void run() {
// Generate all prime numbers from 2 to maxNumber
for (long n = 2; n < maxNumber; n++) {
// Naively test if n is prime.
boolean isPrime = true;
for (long i = 2; i * i < n; i++) {
if (n % i == 0) {
isPrime = false;
break;
}
}
synchronized (lock) {
if (isPrime) {
primes.add(n);
}
numbersChecked = n;
// Notify waiting threads
lock.notifyAll();
}
}
}
}
private static boolean isPrime(long x) {
synchronized (lock) {
// Wait until number checked is greater than x
while (x > numbersChecked) {
try {
lock.wait();
} catch (InterruptedException e) {
break;
}
}
return primes.contains(x);
}
}
public static void main(String[] args) {
Thread thread = new Thread(new PrimeGenerator());
thread.setDaemon(true);
thread.start();
System.out.println(isPrime(15_485_863));
}
}