【问题标题】:Multi-Threaded Java Based Prime Number Generator基于多线程 Java 的素数生成器
【发布时间】:2021-08-30 22:01:54
【问题描述】:

我正在开发一个多线程的素数生成器。我对这个多线程进程的目标是每个进程将检查一个数字。我确实有一些工作代码,但我在“锁定”概念方面遇到了一些问题,其中计划运行 2 个进程彼此非常接近。

Claimed Lock: 0; Claimed Number: 75827; isPrime: false
Claimed Lock: 1; Claimed Number: 75829; isPrime: false
Claimed Lock: 2; Claimed Number: 75831; isPrime: false
Claimed Lock: 4; Claimed Number: 75835; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 3; Claimed Number: 75833; isPrime: true
Claimed Lock: 6; Claimed Number: 75839; isPrime: false.

(您可以看到 2 个锁 - 即 5 个被调用两次 - 它们应该是不同的)

我这个程序的主要目标是让 1 个线程计算基于 1 的素数。根据 Java JVM 向代码内部的 int cores 变量报告的内容,将有 n 个线程。

以下是我的程序的简要说明:

  1. 程序开始获取给定计算机的逻辑 cpu 核心数

  2. 创建一个包含 [2] [CPU 核心数] 的二维数组

  3. Array[0][i] = 填充 2k+1(奇数)个潜在质数(这样做是因为 2 是唯一已知的偶数质数)

  4. Array[1][i] = 填充“-1” = 表示该数字已准备好被进程/线程获取

  5. 然后程序启动 n 个线程(基于 cpu 核心数)

  6. 已经创建的新线程应该寻找下一个可用的 Array[1][i] == -1 并将其更改为值 2。(2 表示进程锁和/或数字是正在检查是否为素数)

    -6a。 n 个子进程检查是否为素数,并将 Array[1][i] 更改为 1 或 0(1 表示它是素数或 0 表示它不是素数)

    -6b。子进程终止

  7. 父进程 - Main 将忙于等待,直到所有 Array[1][i] 为 1 或 0

  8. 重复步骤 3

我在这个逻辑上遗漏了什么或做错了什么?我相信我在 JVM/OS 计划中遗漏了一些东西。但是,我觉得我在这个假设中也可能不正确?我可以做些什么来解决这个问题?

这是我的代码: 多线程类

class MultithreadCalculate extends Thread {
    public void run() {
        try {
            int indexNum = -1;
            for (int i = 0; i < MultiThreadPrimeNumGen.cores; i++) {
                if (MultiThreadPrimeNumGen.primeArray[1][i] == -1) {
                    MultiThreadPrimeNumGen.primeArray[1][i] = 2;
                    indexNum = i;
                    break;
                }
            }

            boolean isPrime = true;
            for (int i = 2; i < MultiThreadPrimeNumGen.primeArray[0][indexNum]; i++) {
                if (MultiThreadPrimeNumGen.primeArray[0][indexNum] % i == 0) {
                    isPrime = false;
                    MultiThreadPrimeNumGen.primeArray[1][indexNum] = 0;
                    break;
                }
            }

            if (isPrime) {
                MultiThreadPrimeNumGen.primeArray[1][indexNum] = 1;
            }

            System.out.println("Thread " + Thread.currentThread().getId() + "; Claimed Lock: " + indexNum + "; Claimed Number: " + MultiThreadPrimeNumGen.primeArray[0][indexNum] + "; isPrime: " + isPrime);
        }
        catch (Exception e) {
            System.out.println("Exception is caught");
        }
    }
}

这里是主类:

public class MultiThreadPrimeNumGen {
    public static int[][] primeArray;
    public static int primeBase = 1;
    public static int cores;

    private static void fillArray() {
        for (int i = 0; i < cores; i++) {
            primeBase += 2;
            primeArray[0][i] = primeBase;
        }

        for (int i = 0; i < cores; i++) {
            primeArray[1][i] = -1;
        }
    }

    public static void main(String[] args) throws FileNotFoundException {
        File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
        PrintWriter out = new PrintWriter(file);

        //Gets number of CPU Cores
        cores = Runtime.getRuntime().availableProcessors();
        System.out.println("Number of Cores: " + cores);

        while (true) {
            primeArray = new int[2][cores];
            fillArray();
            for (int i = 0; i < cores; i++) {
                MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
                multithreadCalculate.start();
            }

            while (true) {
                boolean flag = false;
                for (int i = 0; i < cores; i++) {
                    if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
                        flag = true;
                    } else {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    break;
                }
            }
            for (int i = 0; i < cores; i++) {
                if (primeArray[1][i] == 1) {
                    out.println("PrimeNum: " + primeArray[0][i]);
                    out.flush();
                }
            }
        }
    }
}

【问题讨论】:

  • 我根本看不到任何锁定。为什么两个线程不能同时看到相同的 -1?
  • 我认为我目前对并发编程的了解有点少。我想我认为实现(上面列表中的第 6 步)被认为是一种锁定机制。什么是良好的基本理解的好资源?
  • 您可以查看official tutorial 了解同步的基本介绍。 Java Concurrency in Practice 是一本适合深入学习的好书。
  • 另外,我只想说非常感谢您提供的文档!

标签: java multithreading jvm primes cpu-usage


【解决方案1】:

所以你希望 thread 在循环中填充数组:

Runnable run1 = new Runnable(){
    public void run()
    {
       // Code to fill array
    }
};

Thread thread1 = new Thread(run1);
thread1.start();

Runnable run2 = new Runnable(){
    public void run()
    {
       // Code to fill array
    }
};

Thread thread2 = new Thread2(run2);
thread2.start();

【讨论】:

  • 您能否进一步阐述这一点?我想我对这是什么意思有点困惑?你想让我在新进程产生时“填充数组”吗?
  • 你知道程序逐行运行。您需要一个与主程序或线程分开运行的代码。因此 void fllArray() 可以在线程中使用,以便连续运行
  • 哈哈我知道编程是逐行运行的。父进程只是为对象设置一个特定的数字,然后他们将开始计算它们是否为素数。目标是让这个项目无限循环运行......也就是继续计算素数,直到达到 32 位整数限制。
【解决方案2】:

实际上,我在不使用 Locks 的情况下解决了自己的想法。这个想法来自另一个在这里发帖的用户:Prime Balpreet。所以谢谢!我所做的是在代码中创建 getter 和 setter。这是修改后的代码:

多线程类:

class MultithreadCalculate extends Thread {
    int PrimeNumCalculate = -1;
    int indexNum = -1;

    public int getPrimeNumCalculate() {
        return PrimeNumCalculate;
    }

    public void setPrimeNumCalculate(int primeNumCalculate) {
        PrimeNumCalculate = primeNumCalculate;
    }

    public int getIndexNum() {
        return indexNum;
    }

    public void setIndexNum(int indexNum) {
        this.indexNum = indexNum;
    }

    public void run() {
        try {
            boolean isPrime = true;
            for (int i = 2; i < getPrimeNumCalculate(); i++) {
                if (getPrimeNumCalculate() % i == 0) {
                    isPrime = false;
                    MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
                    MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 0;
                    break;
                }
            }

            if (isPrime) {
                MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
                MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 1;
            }

            System.out.println("Thread " + Thread.currentThread().getId() + "; Index: " + getIndexNum() + "; Number: " + getPrimeNumCalculate() + "; isPrime: " + isPrime);
        }
        catch (Exception e) {
            System.out.println("Exception is caught");
        }
    }
}

这是我的主要课程:

public class MultiThreadPrimeNumGen {
    public static int [][] primeArray;
    public static int primeBase = 1;
    public static int cores;

    private static void fillArray() {
        for (int i = 0; i < cores; i++) {
            primeArray[0][i] = -1;
        }

        for (int i = 0; i < cores; i++) {
            primeArray[1][i] = -1;
        }
    }

    public static void main(String[] args) throws FileNotFoundException {
        File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
        PrintWriter out = new PrintWriter(file);

        cores = Runtime.getRuntime().availableProcessors();
        System.out.println("Number of Cores: " + cores);
        out.println(2);
        out.flush();
        while (true) {
            primeArray = new int[2][cores];
            fillArray();
            for (int i = 0; i < cores; i++) {
                MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
                multithreadCalculate.setPrimeNumCalculate(primeBase += 2);
                multithreadCalculate.setIndexNum(i);
                multithreadCalculate.start();
            }

            while (true) {
                boolean flag = false;
                for (int i = 0; i < cores; i++) {
                    if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
                        flag = true;
                    } else {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    break;
                }
            }
            printMatrix(primeArray);

            for (int i = 0; i < cores; i++) {
                if (primeArray[1][i] == 1) {
                    out.println(primeArray[0][i]);
                }
            }

            out.flush();
        }
    }

    public static void printMatrix(int[][] arr) {
        if (null == arr || arr.length == 0) {
            return;
        }
        int idx = -1;
        StringBuilder[] sbArr = new StringBuilder[arr.length];
        for (int[] row : arr) {
            sbArr[++idx] = new StringBuilder("[\t");
            for (int elem : row) {
                sbArr[idx].append(elem).append("\t");
            }
            sbArr[idx].append("]");
        }
        for (StringBuilder stringBuilder : sbArr) {
            System.out.println(stringBuilder);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-27
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    相关资源
    最近更新 更多