在下面的代码中,多个生产者线程有时会生成相同的质数。如何确保不同的生产者始终生成唯一的质数?
public class UniquePrimes {
private static BlockingQueue<Integer> linkedBlockingQueue = new LinkedBlockingQueue<Integer>();
static ConcurrentHashMap<Integer, String> primesproduced = new ConcurrentHashMap<Integer, String>();
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Enter number of threads you want to create: ");
int NOOFTHREADS = reader.nextInt();
reader.close();
ExecutorService executorPool = Executors.newFixedThreadPool(NOOFTHREADS);
AtomicInteger currentPrime = new AtomicInteger();
Runnable producer = () -> {
String threadName = Thread.currentThread().getName();
int p = 0;
try {
p = generateNextPrime(currentPrime.incrementAndGet());
linkedBlockingQueue.put(p);
primesproduced.put(p, threadName);
System.out.println("Thread " + threadName + " produced prime number " + p);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
List<Runnable> tasks = new ArrayList<Runnable>();
for (int i = 0; i < NOOFTHREADS; i++) {
tasks.add(producer);
}
CompletableFuture<?>[] futures = tasks.stream().map(task -> CompletableFuture.runAsync(task, executorPool))
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();
executorPool.shutdown();
System.out.println("\nTotal unique primes produced: " + primesproduced.size() + " and they are: ");
System.out.print(
primesproduced.entrySet().stream().filter(map -> map.getKey().intValue()>0).map(k -> "[" + k + "]").collect(Collectors.joining(",")));
}
}
private static int generateNextPrime(int currentPrime) {
currentPrime++;
if (currentPrime < 2) {
currentPrime = 2;
return currentPrime;
}
for (int i = 2; i < currentPrime; i++) {
if (currentPrime % i == 0) {
currentPrime++;
i = 2;
} else {
continue;
}
}
return currentPrime;
}
}
当前,多个生产者可以产生相同的原始价值。
如何确保每个生产者产生的新原始价值都没有其他生产者以前产生的?
谢谢你的帮助。
最佳答案
您需要不同的策略。您当前的策略是让线程从currentPrime + 1
开始搜索素数。由于每个线程都在做相同的事情,这意味着它们将在重叠区域搜索素数。这是低效率的(重复的工作),并且导致两个或多个线程偶尔发现相同的素数。
更好的策略是确保每个线程搜索不同的范围。例如
value = atomicInt.addAndGet(1000);
在成功添加之前,将
atomicInt
加1000,并将value
设置为atomicInt
的值。因此,您可以将value
作为分配给当前线程以进行搜索的1000个整数范围的开始。另一个提示:如果想要更好的性能,请查看Sieve of Eratosthenes。
我猜您是在做作业或学习练习,所以我不会为您编写代码。