该程序运行4个线程并搜索从1到100的素数。有时2个线程同时攻击并且数字重复。我试图同步线程,但我不知道如何做得好。我可以帮忙吗?抱歉我的英文不好
import java.util.ArrayList;
public class EjemploThread1 extends Thread{
static int numero=1;
static ArrayList<Integer> primos = new ArrayList<Integer>() ;
public synchronized void run() {
//try {
while (numero < 100){
numero++;
if (!primos.contains(numero) && esPrimo(numero))
{
primos.add(numero);
}
notifyAll();
//yield();
try {
sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//MAIN
public static void main(String[] args) throws InterruptedException {
EjemploThread1 hilos = null;
int n_hilos=4;
//Crear los 4 Hilos
for (int i=0;i<=n_hilos;i++) {
hilos = new EjemploThread1();
hilos.start();
}
for (int i=0;i<=n_hilos;i++) {
hilos.join();
}
//cuando finalizen los hilos(join) continuara y mostrara el vector:
System.out.println("\nVECTOR NUMEROS PRIMOS: ");
for(int i=0; i < primos.size(); i++)
{
System.out.print(primos.get(i) + " ");
}
}
//FUNCION SABER SI ES PRIMO
public static boolean esPrimo(int numero)
{
for(int i=2; i<numero; i++)
{
if(numero % i == 0) return false; //no es primo
}
return true; //es primo
}
}
答案 0 :(得分:2)
初始化搜索空间时,在Thread
s之间划分搜索空间会更容易,因此没有重叠。不需要笨重的同步。这样的事情。
public class PrimeFinder implements Runnable {
private int rangeStart;
private int rangeEnd;
public PrimeFinder(int start, int end) {
rangeStart = start;
rangeEnd = end;
}
public void run() {
//check for primes where rangeStart <= x <= rangeEnd
}
}
...然后在main
...
public static void main(String[] args) {
new Thread(new PrimeFinder(0, 25)).start();
new Thread(new PrimeFinder(26, 50)).start();
//and so on
}
作为附注,使用synchronized
run
方法的Thread
方法Thread
是没用的。每个run
都有自己的public static synchronized void addPrime(int prime) {
if(!primos.contains(prime)) {
primos.add(prime);
}
}
方法,因此没有其他任何东西可以竞争特定的锁。
回应你的评论:
如果您强制以这种方式执行此操作并且不希望将重复的数字添加到列表中,则可以同步包装器方法以添加素数:
Thread
这将确保您不会重复。然后在您的if(esPrimo(numero)) {
addPrime(numero);
}
中,您将拥有:
{{1}}
答案 1 :(得分:0)
而不是同步run()
,您可以同步静态arrayList primos:
List primos = Collections.synchronizedList(new ArrayList<Integer>());
这确保没有两个线程将测试相同的数字
答案 2 :(得分:0)
我认为在run()
上同步Runnable
绝不是一个好主意。我只需将numero声明为volatile
或将其类型更改为AtomicInteger