目前,我正在尝试用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已经检查过了)
计数器应该是所有线程共享的值,因此从一个线程递增它会影响所有并发线程。
最简单的方法是使用静态
字段。然后使用某种同步来避免线程同时递增/读取计数器。
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中将 nodeIntegrationInWorker选项设置为 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: {