java - 当其中一个找到素数时如何停止线程
问题描述
当找到一个素数时,我必须阻止它。当我在 之前使用synchronizedwhile
时,只会发生一个线程进程。但是,应该发生多个线程操作,但是当找到素数时,所有线程都应该停止。
控制部分的初始值i
已更改。
我想要做的是使用锁定和同步找到素数。
public abstract class NumberGenerator {
private boolean isStop;
public abstract int generateNumber();
public void stop() {
this.isStop = true;
}
public boolean isStopped() {
return isStop;
}
}
public class IntegerNumberGenerator extends NumberGenerator {
private Random random;
int randomAtama;
public IntegerNumberGenerator() {
this.random = new Random();
}
@Override
public int generateNumber() {
return random.nextInt(100) + 1;
}
}
public class PrimeNumberChecker implements Runnable {
private NumberGenerator generator;
private Lock lock = new ReentrantLock();
public Condition continueLock = lock.newCondition();
public PrimeNumberChecker(NumberGenerator generator) {
this.generator = generator;
}
@Override
public void run() {
while (!generator.isStopped()) {
int number = generator.generateNumber();
System.out.println(Thread.currentThread().getName() + " generated " + number);
if (check(number)) {
System.out.println(number + " is prime !");
generator.stop();
}
}
}
public static boolean check(int number) {
boolean result = true;
for (int i = 2; i <= number / 2; i++) {
if ((number % i) == 0) {
result = false;
}
}
return result;
}
}
public class Driver {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
NumberGenerator numberGenerator = new IntegerNumberGenerator();
for (int i = 0; i < 5; i++) {
executorService.execute(new PrimeNumberChecker(numberGenerator));
}
executorService.shutdown();
}
}
解决方案
您可以将检查方法优化为:
public static boolean check(int number) {
for (int i = 2; i <= number / 2; i++) {
if ((number % i) == 0) {
return false;
}
}
return true;
}
一旦你知道这个数字不是素数,你就可以早点返回。
当我找到一个质数时,我必须停止它。如果我在 synchronized while 之前使用它,只会发生一个线程进程。应该发生多个线程操作,但应该在找到素数时停止。
您可以通过向标志添加第一个volatile来实现此目的:isStop
private volatile boolean isStop = false;
generator.isStopped()
然后在确定数字是否为素数的方法中检查(也):
public boolean check(int number) {
for (int i = 2; i <= number / 2; i++) {
if (generator.isStopped() || number % i == 0) {
return false;
}
}
return true;
}
最后,您需要在读取check
方法的值时进行同步,因为可能会发生多个线程同时找到素数的情况。因此,将您的代码调整为:
boolean result = check(number); // All threads to work in parallel
synchronized (generator) {
if (result && !generator.isStopped()) {
System.out.println(number + " is prime !");
generator.stop();
}
}
这里的volatile是不够的,因为多个线程可能会设法进入
if(result && !generator.isStopped())
在其中一个能够实际调用之前generator.stop()
;。由于完全相同的原因,isStop
AtomicBoolean
单独制作变量也无济于事。
关键是语句!generator.isStopped()
,并且generator.stop();
必须在同一个关键区域内执行,要么使用同步,要么在同一个过程中原子地执行这两个操作。因此,为了AtomicBoolean
工作,您必须执行以下操作:
public abstract class NumberGenerator {
private final AtomicBoolean isStop = new AtomicBoolean(false);
public abstract int generateNumber();
public void stop() {
this.isStop.set(true);
}
public boolean isStopped() {
return isStop.get();
}
public boolean getAndSet(){
return isStop.getAndSet(true);
}
}
和
if (check(number) && !generator.getAndSet()) {
System.out.println(number + " is prime !");
}
因为它getAndSet
是原子完成的,所以您不会冒让多个线程打印出它们的素数的风险。
我想要做的是使用锁定和同步找到素数。
如果您的意思是只使用一个或另一个(因为您不需要同时使用两者),那么您可以执行以下操作:
boolean result = check(number);
synchronized (generator) {
if (result && !generator.isStopped()) {
System.out.println(number + " is prime !");
generator.stop();
}
}
即使没有volatile ,这也可以工作。
推荐阅读
- flutter - 运行项目时出现“package_config.json 不存在”错误
- angular - 或条件 Firestore 和 Angular
- java - 如何按数字顺序对字符串和数字列表进行排序?
- discord.js - Discord bot TypeError:无法读取未定义的属性“forEach”
- python - 给定代码的逻辑是否正确?该代码旨在在给定条件为 True 时进行累积和
- node.js - 与两台服务器的快速会话
- javascript - 在组件中加载 node_module 包时,窗口未定义错误
- javascript - 我应该如何在打字稿中为“依赖”函数参数编写类型?
- mysql - SQL 中的丢弃漏斗
- python - 如何在 django 中更有效地访问这些表