【问题标题】:Finding Number of Cores in Java在 Java 中查找内核数
【发布时间】:2011-06-13 04:10:15
【问题描述】:

如何从 Java 代码中找到我的应用程序可用的内核数量?

【问题讨论】:

  • 几乎所有意图和目的都是“核心 == 处理器”。
  • 使用纯 Java 很难找到机器物理上的内核数量。使用 Runtime.getRuntime().availableProcessors() 可以很容易地找到 Java 程序在启动时可以使用的内核数。由于所有主要的现代操作系统都能够设置 CPU 亲和性(即将应用程序限制在一定数量的内核上),因此需要牢记这一点。
  • 逻辑核心还是物理核心?有一个重要的区别。

标签: java


【解决方案1】:

如果你想将你机器上的内核数量与你的 java 程序给你的数量核对一下。

在 Linux 终端中:lscpu

在 Windows 终端 (cmd) 中:echo %NUMBER_OF_PROCESSORS%

在 Mac 终端中:sysctl -n hw.ncpu

【讨论】:

    【解决方案2】:

    如果您想获取物理核心数,您可以运行 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;
    }
    

    OSValidator 类:

    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.indexOf("win") >= 0);
    }
    
    public static boolean isMac() {
        return (OS.indexOf("mac") >= 0);
    }
    
    public static boolean isUnix() {
        return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0 );
    }
    
    public static boolean isSolaris() {
        return (OS.indexOf("sunos") >= 0);
    }
    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";
        }
    }
    

    }

    【讨论】:

    • 这是一段非常适合 OOP 的代码。 :)
    • OSValidator 类支持 OSX,但 getNumberOfCores 完全忽略它。顺便说一句,blog.opengroup.org/2015/10/02/… 所以 'Mac' 应该在你的 isUnix() 中,但是......对于 BSD、OSX,不存在 lscpu 命令并且你的 getNumberOfCores 将返回 0。
    • 在 Linux 上,您必须通过“Socket(s)”为多个“Core(s) per socket”。另外,我会使用正则表达式。
    • 最好使用“OS.contains()”而不是“OS.indexOf()”。它提高了可读性并且减少了输入。
    【解决方案3】:

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

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

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

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

    centralProcessor.getLogicalProcessorCount();
    

    【讨论】:

    • 这也将允许您使用centralProcessor.getPhysicalProcessorCount(),这可能是目前java 中获取该信息的最佳方式。如果您的线程几乎总是有工作要做,并且您想知道可以启动的此类线程的数量,同时仍为其他线程和进程留下明确定义的剩余 CPU 容量,那么计算应该是这个数字基于。
    【解决方案4】:

    这适用于安装了 Cygwin 的 Windows:

    System.getenv("NUMBER_OF_PROCESSORS")

    【讨论】:

    • 我已经安装了 Cygwin,但这可以在 Windows shell 中运行:groovy -e "println System.getenv('NUMBER_OF_PROCESSORS')"
    • 我不知道这是否是标准的 Windows 环境变量,但是:set NUMBER_OF_PROCESSORS 在 Windows 命令行中为我工作。
    【解决方案5】:
    int cores = Runtime.getRuntime().availableProcessors();
    

    如果cores 小于 1,则说明您的处理器即将死机,或者您的 JVM 存在严重错误,或者宇宙即将爆炸。

    【讨论】:

    • 这将为您提供逻辑线程的数量。例如如果您启用了超线程,这将是内核数量的两倍。
    • @Peter,是的,好点。使用 i7 机器执行此操作时,我感觉自己是山丘之王! :)
    • @Peter Lawrey:它只给出了 JVM 实际可用的逻辑线程数(我猜是在启动时)。使用 CPU 亲和性,用户/操作系统可以限制 JVM 看到的“核心”数量。您甚至可以在正在运行的 JVM 上执行此操作,但我不太确定这会如何影响 availableProcessors()
    • @PeterLawrey:这似乎是不正确的,availableProcessors() 的 Java 文档说“这个值可能会在虚拟机的特定调用期间发生变化。对可用处理器数量敏感的应用程序应该因此偶尔会轮询此属性并适当调整其资源使用情况。” source
    • @universe 爆炸等:或者机器实际上有超过 2,147,483,647 个可用的逻辑线程? ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    相关资源
    最近更新 更多