目前我正在嘗試使用java中的執行緒來實作一個prime finder。不幸的是,它似乎并沒有按照我想要的方式作業。
我基本上想要的是我有一個 while(true) 回圈來無限期地生成數字。生成數字后,執行緒應獲取該數字并檢查它是否為質數。當第一個執行緒仍在檢查素數時,第二個執行緒已經抓住了下一個數字來檢查素數,依此類推。
現在數字生成確實有效,但所有執行緒似乎都使用相同的數字,這對我的實作毫無意義。
這是我專案的當前狀態:
public class Main {
public static void main(String[] args) {
int logicalCores = Runtime.getRuntime().availableProcessors();
int startFrom = 0;
startCalc(logicalCores, startFrom);
}
public static void startCalc(int threadCount, int startFrom){
for (int i = 0; i < threadCount; i ){
PrimeCalculator calculator = new PrimeCalculator(startFrom, i);
Thread thread = new Thread(calculator);
thread.start();
}
}
}
import static java.lang.Thread.sleep;
public class PrimeCalculator implements Runnable{
int startingCounter;
int id;
public PrimeCalculator(int counter, int id){
this.startingCounter = counter;
this.id = id;
}
@Override
public void run() {
Integer counter = startingCounter;
while(true){
if (isPrime((counter))){
System.out.printf("Thread with ID %d found that %d is a prime! \n", id, counter );
try{
sleep(10000);
} catch (Exception e){
}
}
synchronized (counter){
counter ;
}
}
}
public static boolean isPrime(int n)
{
if (n == 2 || n == 3 || n == 5) return true;
if (n <= 1 || (n&1) == 0) return false;
for (int i = 3; i*i <= n; i = 2)
if (n % i == 0) return false;
return true;
}
}
問題是所有執行緒似乎都在不斷檢查相同的數字。例如,數字是 2,但我的 CPU 的所有 16 個執行緒都檢查素數,而實際上像 Thread0 這樣的執行緒應該檢查數字 2 的素數,而其他執行緒已經在檢查計數器的增量(例如 Thread15 已經在 16)等。
編輯:
我想我需要舉一個更好的例子來說明預期的行為。
假設我有一臺 4 核 4 執行緒的計算機。這將使我的主要方法 4 中的logicalCores 變數,并在函式“startCalc”中創建 4 個執行緒。
現在回圈應該從定義的起點生成數字。假設那個點是 0。現在應該發生的是一個執行緒,我們稱之為 thread0 正在獲取該數字并檢查它是否是素數。與此同時,回圈產生了一個計數器的增量,現在位于“1”。現在,因為 thread0 仍在檢查 0 是否為素數,所以第二個執行緒 thread1 使用值“1”獲取當前計數器并檢查“1”是否為素數。
這里的目標是每個執行緒都以防止重復檢查的方式檢查素數。例如(我們不希望 thread0 檢查 1 是否是素數,因為 thread1 已經這樣做了)
uj5u.com熱心網友回復:
您的計數器應該是所有執行緒共享的值,以便從一個執行緒遞增它會影響所有并發執行緒。
最簡單的方法是使用static欄位。然后使用某種同步來避免執行緒同時遞增/讀取計數器。
public class Main {
public static void main(String[] args) {
int logicalCores = Runtime.getRuntime().availableProcessors();
int startFrom = 0;
startCalc(logicalCores, startFrom);
}
public static void startCalc(int threadCount, int startFrom) {
PrimeCalculator.startAt(startFrom); //Set this for all threads
for (int i = 0; i < threadCount; i ) {
PrimeCalculator calculator = new PrimeCalculator(i);
Thread thread = new Thread(calculator);
thread.start();
}
}
}
import static java.lang.Thread.sleep;
public class PrimeCalculator implements Runnable {
static int counter; //Use static variable
int id;
public static void startAt(int counterStart) { //Set start once for all threads
counter = counterStart;
}
public PrimeCalculator(int id) {
this.id = id;
}
@Override
public void run() {
while (true) {
int current = incrementAndGetCounter();
if (isPrime((current))) {
System.out.printf("Thread with ID %d found that %d is a prime! \n", id, current);
try {
sleep(1000);
} catch (Exception e) {
}
}
}
}
public static boolean isPrime(int n) {
if (n == 2 || n == 3 || n == 5)
return true;
if (n <= 1 || (n & 1) == 0)
return false;
for (int i = 3; i * i <= n; i = 2)
if (n % i == 0)
return false;
return true;
}
//Use synchronized method to increment and get value
//to prevent one thread incrementing it while another one is reading it
private static synchronized int incrementAndGetCounter() {
return counter ;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/463836.html
