在Java中查找核心数

483

我如何从Java代码中查找我的应用程序可以使用的核心数量?


3
从几乎所有的意图来看,“core == processor”可以理解为“核心等同于处理器”。 - Joachim Sauer
38
使用纯Java来找到机器物理核心数很困难。但是,在启动时使用*Runtime.getRuntime().availableProcessors()*可以轻松地找到Java程序可以使用的处理器数量。由于所有主要现代操作系统都能够设置CPU亲和性(即限制应用程序仅使用特定数量的核心),因此这是需要注意的问题。 - SyntaxT3rr0r
10
逻辑核心还是物理核心?两者有重要区别。 - arkon
另请参见:https://dev59.com/JXI-5IYBdhLWcg3wMFMf - Christophe Roussy
5个回答

874
int cores = Runtime.getRuntime().availableProcessors();

如果 cores 小于1,那么可能是您的处理器即将死亡,或者您的JVM存在严重的错误,或者宇宙即将爆炸。


139
这将给你逻辑线程的数量。例如,如果你开启了超线程,这个数字将是核心数的两倍。 - Peter Lawrey
19
@Peter Lawrey: 这只是给出JVM实际可用逻辑线程数的数字(我猜在启动时)。使用CPU亲和力,用户/操作系统可以限制JVM看到的“核心”数量。甚至可以在运行中的JVM上执行此操作,但我不确定这会如何影响*availableProcessors()*的结果。 - SyntaxT3rr0r
31
@PeterLawrey似乎不正确,Java文档中有关availableProcessors()的内容是:“在特定虚拟机调用期间,这个值可能会发生变化。敏感于可用处理器数量的应用程序因此应该偶尔轮询此属性并相应地调整其资源使用。”来源 - JW.
13
“@universe blowing up and such : or the machine actually has more than 2,147,483,647 logical threads available ? ;)” 可以翻译为:“@宇宙大爆炸之类的事情:或者这台机器实际上有超过 2,147,483,647 个逻辑线程可用吗?;)” - Pierre Henry
7
我可以确认在Windows 7 SP1 x64系统上,使用Java 1.7.0_51版本时,availableProcessors()函数会随着CPU亲和性的改变而改变。你可以用jrunscript调用java.lang.Runtime.getRuntime().availableProcessors()来进行测试,通过Windows任务管理器改变jrunscript.exe的处理器亲和性,并再次运行availableProcessors()函数,你会发现可用处理器数量会发生变化。 - Simon Kissane
显示剩余11条评论

36
如果您想获取物理核心数,可以运行 cmd 和终端命令,然后解析输出以获取所需信息。下面是一个显示返回物理核心数的函数。
private int getNumberOfCPUCores() {
    OSValidator osValidator = new OSValidator();
    String command = "";
    if(osValidator.isMac()){
        command = "sysctl -n machdep.cpu.core_count";
    }else if(osValidator.isUnix()){
        command = "lscpu";
    }else if(osValidator.isWindows()){
        command = "cmd /C WMIC CPU Get /Format:List";
    }
    Process process = null;
    int numberOfCores = 0;
    int sockets = 0;
    try {
        if(osValidator.isMac()){
            String[] cmd = { "/bin/sh", "-c", command};
            process = Runtime.getRuntime().exec(cmd);
        }else{
            process = Runtime.getRuntime().exec(command);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getInputStream()));
    String line;

    try {
        while ((line = reader.readLine()) != null) {
            if(osValidator.isMac()){
                numberOfCores = line.length() > 0 ? Integer.parseInt(line) : 0;
            }else if (osValidator.isUnix()) {
                if (line.contains("Core(s) per socket:")) {
                    numberOfCores = Integer.parseInt(line.split("\\s+")[line.split("\\s+").length - 1]);
                }
                if(line.contains("Socket(s):")){
                    sockets = Integer.parseInt(line.split("\\s+")[line.split("\\s+").length - 1]);
                }
            } else if (osValidator.isWindows()) {
                if (line.contains("NumberOfCores")) {
                    numberOfCores = Integer.parseInt(line.split("=")[1]);
                }
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    if(osValidator.isUnix()){
        return numberOfCores * sockets;
    }
    return numberOfCores;
}

操作系统验证器类:

public class OSValidator {

private static String OS = System.getProperty("os.name").toLowerCase();

public static void main(String[] args) {

    System.out.println(OS);

    if (isWindows()) {
        System.out.println("This is Windows");
    } else if (isMac()) {
        System.out.println("This is Mac");
    } else if (isUnix()) {
        System.out.println("This is Unix or Linux");
    } else if (isSolaris()) {
        System.out.println("This is Solaris");
    } else {
        System.out.println("Your OS is not support!!");
    }
}

public static boolean isWindows() {
    return (OS.contains("win"));
}

public static boolean isMac() {
    return (OS.contains("mac"));
}

public static boolean isUnix() {
    return (OS.contains("nix") || OS.contains("nux") || OS.contains("aix") );
}

public static boolean isSolaris() {
    return (OS.contains("sunos"));
}
public static String getOS(){
    if (isWindows()) {
        return "win";
    } else if (isMac()) {
        return "osx";
    } else if (isUnix()) {
        return "uni";
    } else if (isSolaris()) {
        return "sol";
    } else {
        return "err";
    }
}

}

->

}


4
这是一段很适合面向对象编程(OOP)的代码。 :) - Lyubomyr Shaydariv
1
OSValidator类支持OSX,但getNumberOfCores方法完全忽略了它。另外,https://blog.opengroup.org/2015/10/02/mac-os-x-el-capitan-achieves-unix-certification/ 表明'Mac'应该包含在isUnix()中,但是对于BSD、OSX,不存在lscpu命令,因此getNumberOfCores将返回0。 - Paul Hargreaves
1
在Linux上,您必须将“每个插座的核心数”乘以“插座数”。此外,我建议使用正则表达式。 - Aleksandr Dubinsky
2
最好使用 "OS.contains()" 而不是 "OS.indexOf()"。它提高了可读性,打起来也更少。 - JWCompDev

14

这是另一种查找CPU核心数量(以及许多其他信息)的方法,但是此代码需要额外的依赖:

本机操作系统和硬件信息 https://github.com/oshi/oshi

SystemInfo systemInfo = new SystemInfo();
HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware();
CentralProcessor centralProcessor = hardwareAbstractionLayer.getProcessor();

获取可用于处理的逻辑CPU数量:

centralProcessor.getLogicalProcessorCount();

1
这也将让您使用centralProcessor.getPhysicalProcessorCount(),这可能是目前在Java中获取该信息的最佳方式。如果您有几乎始终有工作要做的线程,并且您想知道可以启动多少此类线程,同时仍然为其他线程和进程留下明确定义的CPU容量,那么计算应基于此数字。 - malamut

1
如果你想要确认你的机器有多少个核心,与你的Java程序所给出的数字相匹配。
在Linux终端中:lscpu
在Windows终端(cmd)中:echo %NUMBER_OF_PROCESSORS%
在Mac终端中:sysctl -n hw.ncpu

1
%NUMBER_OF_PROCESSORS% 输出逻辑核心数。 - alper

-7

这个在安装了Cygwin的Windows上可以运行:

System.getenv("NUMBER_OF_PROCESSORS")


我已经安装了Cygwin,但是这个命令需要在Windows shell中运行:groovy -e "println System.getenv('NUMBER_OF_PROCESSORS')" - AbuNassar
我不确定这是否是标准的Windows环境变量,但是:set NUMBER_OF_PROCESSORS在Windows命令行中可以使用。 - AbuNassar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接