私は、並行して素数を生成する2つの実装をしました。コアコードは、ここにStackOverflowで別のポストから取得されます。
私は、これらの実装の1つが好ましく、なぜされている知りたいですか?また、このためのより良い、より速く解決策がある場合は?
実装1:
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class PrimeThreads {
private static int currentPrime = 0;
public static void main(String[] args) {
Object lock = new Object();
Thread primerGenThread = new Thread(() -> {
String threadName = Thread.currentThread().getName();
System.out.println("Starting thread: " + threadName);
int currentPrimeNo = 0;
synchronized (lock) {
try {
currentPrimeNo = generateNextPrime();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Prime Number Associated with this thread " + threadName + " is: " + currentPrimeNo);
System.out.println("Completed thread: " + threadName);
});
System.out.println("****This is where the project starts*****");
Scanner reader = new Scanner(System.in);
System.out.print("Enter number of threads you want to create: ");
int n = reader.nextInt();
reader.close();
ExecutorService executor = Executors.newFixedThreadPool(n);
for(int i=1;i<=n; i++) {
executor.submit(primerGenThread);
}
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("****This is where the project ends*****");
}
private static int generateNextPrime() throws InterruptedException {
long startTime = System.nanoTime();
currentPrime++;
if (currentPrime < 2) {
currentPrime = 2;
return currentPrime;
}
for (int i = 2; i < currentPrime; i++) {
if (currentPrime % i == 0) {
currentPrime++;
i = 2;
} else {
continue;
}
}
long endTime = System.nanoTime();
System.out.println("Time taken: " + (endTime - startTime) + " naoseconds.");
return currentPrime;
}
}
そして、実装2:
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class PrimeAsyncThreads {
private static int currentPrime = 0;
public static void main(String[] args) {
System.out.println("****This is where the project starts*****");
Scanner reader = new Scanner(System.in);
System.out.print("Enter number of threads you want to create: ");
int n = reader.nextInt();
reader.close();
ExecutorService executor = Executors.newFixedThreadPool(n);
for (int i = 1; i <= n; i++) {
CompletableFuture.supplyAsync(() -> {
try {
return generateNextPrime();
} catch (InterruptedException e) {
e.printStackTrace();
}
return n;
}, executor).thenAccept(s -> System.out.println("Prime Number Associated with this thread "
+ Thread.currentThread().getName() + " is: " + currentPrime));
}
executor.shutdown();
try {
executor.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("****This is where the project ends*****");
}
private static int generateNextPrime() throws InterruptedException {
long startTime = System.nanoTime();
currentPrime++;
if (currentPrime < 2) {
currentPrime = 2;
return currentPrime;
}
for (int i = 2; i < currentPrime; i++) {
if (currentPrime % i == 0) {
currentPrime++;
i = 2;
} else {
continue;
}
}
long endTime = System.nanoTime();
System.out.println("Time taken: " + (endTime - startTime) + " naoseconds.");
return currentPrime;
}
}
あなたの提案に感謝し、役立ちます。
編集:また、第2の実施は各スレッドが新しい首相を取得することを保証するものではないことに気づきました。この場合、時には複数のスレッドがcurrentPrime変数の同じ値を取得します。
ありがとうございました。
これらの実装の主な違いは、それらが実行されている方法です。
Implempentation 1は、順次実行に基本的に等しいです。同期ブロックを使用する方法ためのスレッドを使用することの利点はありません。すべてのスレッドは、次の素数が生成される前に完了する前のスレッドを待ちます。
あなたは既に実装2は、同一の素数を複数回計算していることに気づきました。何の同期がないからです。唯一のカウンタは、currentPrime
数は次のスレッドで首相として考慮すべき制御のいくつかの方法を持っているために使用されます。
したがって、両方の実装では、実行可能な結果を生成するために並列に素数を計算することができません。
ルーチンについて考えてみよう。あなたはその素数かどうかを判断するために値を使用します。この値は、計算を行うために、すべてのスレッドで入力してください。今、考慮すべき唯一のことは、それが一度だけ使用されていることを確認するために、この値はスレッドセーフで作成する方法です。
これがためにアトミック変数を使って、例えば、achivedすることができますcurrentPrime
。
別の改善は、インクリメントすることができcurrentPrime
外generateNextPrime()
の方法。このメソッドは、パラメータとして値を取ることができます。何かのようなもの
generateNextPrime(currentPrime.incrementAndGet());