当前位置: 首页 > 知识库问答 >
问题:

多线程Prime finder Java

钦英发
2023-03-14

目前,我正在尝试用java中的线程实现一个prime finder。不幸的是,它似乎并没有按照我的预期工作。

我基本上想要的是,我有一个无限生成数字的时(真)循环。在一个数字生成后,一个线程应该抓取那个数字并检查它是否是素数。当第一个线程还在检查素数时,第二个线程已经抓取了下一个数字来检查素数等等。

现在数字生成确实有效,但是所有线程似乎都使用相同的数字,这对我的实现没有意义。

以下是我的项目的当前状态:

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”是否为素数。

这里的目标是,每个线程都以防止重复检查的方式检查一个素数。e、 g(我们不希望thread0检查1是否为素数,因为thread1已经检查过了)

共有1个答案

罗浩然
2023-03-14

计数器应该是所有线程共享的值,因此从一个线程递增它会影响所有并发线程。

最简单的方法是使用静态字段。然后使用某种同步来避免线程同时递增/读取计数器。

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++;
  }
}
 类似资料:
  • typora-copy-images-to: img 1. 多线程概述 人们在日常生活中,很多事情都是可以同时进行的。例如,一个人可以一边听音乐,一边打扫房间,可以一边吃饭,一边看电视。在使用计算机时,很多任务也是可以同时进行的。例如,可以一边浏览网页,一边打印文档,还可以一边聊天,一边复制文件等。计算机这种能够同时完成多项任务的技术,就是多线程技术。Java是支持多线程的语言之一,它内置了对多线

  • 使用 [Web Workers][web-workers]可以在系统级线程中运行JavaScript。 多线程Node.js 在 webPreferences中将 n​​odeIntegrationInWorker选项设置为 true,可以在Electron的Web Workers中使用Node.js功能: 1 let win = new BrowserWindow({ 2 webPreferen

  • If you use Casbin in a multi-threading manner, you can use the synchronized wrapper of the Casbin enforcer: https://github.com/casbin/casbin/blob/master/enforcer_synced.go (GoLang) and https://github.

  • 多线程 Swift多线程编程方案 Thread Cocoa Operation (Operation 和 OperationQueue) Grand Central Dispath (GCD) 1. Thread在三种多线程技术中是最轻量级的, 但需要自己管理线程的生命周期和线程同步. 线程同步对数据的加锁会有一定的系统开销. detachNewThread(_ block: @escaping

  • 在多线程运行环境中, Configuration 实例, Template 实例和数据模型应该是永远不能改变(只读)的对象。 也就是说,创建和初始化它们(如使用 set... 方法)之后,就不能再修改它们了(比如不能再次调用 set... 方法)。 这就允许我们在多线程环境中避免代价很大的同步锁问题。要小心 Template 实例; 当使用了 Configuration.getTemplate 方

  • 多任务可以由多进程完成,也可以由一个进程内的多线程完成。 我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程。 由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程。 Python的标准库提供了两个模块:thread和threading,thread是低级模块,th

  • 多任务可以由多进程完成,也可以由一个进程内的多线程完成。 我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程。 由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程。 Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,

  • 通过Web Workers,可以实现用操作系统级别的线程来跑JavaScript 多线程的Node.js 可以在Electron的Web Workers里使用Node.js的特性。要用的话,需把webPreferences中的nodeIntegrationInWorker选项设置为true const win = new BrowserWindow({ webPreferences: {