Localizando número de núcleos em Java

411

Como posso encontrar o número de núcleos disponíveis para meu aplicativo no código Java?

Damir
fonte
3
Para praticamente todas as intenções e propósitos "core == processador".
Joachim Sauer
32
é difícil encontrar o número de núcleos que a máquina possui fisicamente usando puramente Java. Encontrar o número de núcleos que o programa Java pode usar na inicialização é fácil, usando Runtime.getRuntime (). AvailableProcessors () . Devido à capacidade de todos os principais sistemas operacionais modernos definirem a afinidade da CPU (ou seja, restringir um aplicativo a apenas um certo número de núcleos), é uma preocupação a ter em mente.
SyntaxT3rr0r
6
Núcleos lógicos ou físicos? Há uma diferença importante.
b1nary.atr0phy
Veja também: stackoverflow.com/questions/1980832/…
Christophe Roussy

Respostas:

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

Se coresfor menor que um, seu processador está prestes a morrer ou sua JVM tem um bug sério ou o universo está prestes a explodir.

darioo
fonte
107
Isso fornecerá o número de threads lógicos. Por exemplo, se você estiver usando o hyperthreading, isso será o dobro do número de núcleos.
precisa saber é o seguinte
6
@ Peter, sim, bom ponto. Eu me senti o rei da colina ao executar esta ação com a minha máquina i7! :)
Bart Kiers
14
@ Peter Lawrey: apenas fornece o número de threads lógicos realmente disponíveis para a JVM (na inicialização, eu acho). Usando a afinidade da CPU, o usuário / sistema operacional pode restringir o número de "núcleos" que uma JVM vê. Você pode até fazer isso em uma JVM em execução, mas não tenho muita certeza de como isso influencia os availableProcessors () .
precisa saber é o seguinte
25
@ PeterLawrey: isso parece estar incorreto, a documentação Java para availableProcessors () diz "Este valor pode mudar durante uma chamada específica da máquina virtual. Os aplicativos sensíveis ao número de processadores disponíveis devem, ocasionalmente, pesquisar esta propriedade e ajustar suas propriedades. uso adequado de recursos ". fonte
JW.
9
@universe explodindo e coisas assim: ou a máquina realmente tem mais de 2.147.483.647 threads lógicos disponíveis? ;)
Pierre Henry
26

Se você deseja obter o número de núcleos físicos, pode executar o comando cmd e terminal e, em seguida, analisar a saída para obter as informações necessárias. Abaixo é mostrada a função que retorna o número de núcleos físicos.

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;
}

Classe 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";
    }
}

}

adi9090
fonte
4
Este é um pedaço de código que é um bom candidato a ser colocado em OOP. :)
Lyubomyr Shaydariv
1
A classe OSValidator suporta OSX, mas o getNumberOfCores a ignora completamente. Como um aparte, blog.opengroup.org/2015/10/02/… então 'Mac' deve estar em seu isUnix (), mas ... Para BSD, OSX, não existe nenhum comando lscpu e seu getNumberOfCores retornará 0.
Paul Hargreaves
1
No Linux, você deve ter vários "Núcleo (s) por soquete" por "Socket (s)". Além disso, eu usaria expressões regulares.
Aleksandr Dubinsky
1
É melhor usar "OS.contains ()" em vez de "OS.indexOf ()". Melhora a legibilidade e é menos digitado.
Josh Gager
6

Essa é uma maneira adicional de descobrir o número de núcleos da CPU (e muitas outras informações), mas esse código requer uma dependência adicional:

Informações sobre hardware e sistema operacional nativo https://github.com/oshi/oshi

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

Obtenha o número de CPUs lógicas disponíveis para processamento:

centralProcessor.getLogicalProcessorCount();
Antonio
fonte
Isso também permitirá que você use centralProcessor.getPhysicalProcessorCount (), que provavelmente é atualmente a melhor maneira em java para obter essas informações. Se você possui threads que quase sempre têm trabalho a fazer e deseja saber o número de threads, você pode iniciar enquanto ainda deixa uma sobra bem definida da capacidade da CPU para outros threads e processos, esse é o número que o cálculo deve ser baseado em.
malamut
-3

Isso funciona no Windows com o Cygwin instalado:

System.getenv("NUMBER_OF_PROCESSORS")

Lyle Z
fonte
Eu tenho Cygwin instalado, mas isso funciona a partir do shell do Windows:groovy -e "println System.getenv('NUMBER_OF_PROCESSORS')"
AbuNassar
Não sei se essa é uma variável de ambiente padrão do Windows, mas: set NUMBER_OF_PROCESSORSfunciona a partir da linha de comando do Windows para mim.
AbuNassar 01/04