Quantos threads uma Java VM suporta?


212

Quantos threads uma Java VM suporta? Isso varia de acordo com o fornecedor? pelo sistema operacional? outros fatores?

Respostas:


170

Isso depende da CPU que você está usando, do sistema operacional, do que outros processos estão fazendo, do release de Java que você está usando e de outros fatores. Eu já vi um servidor Windows ter> 6500 Threads antes de desligar a máquina. A maioria dos threads não estava fazendo nada, é claro. Quando a máquina atingiu cerca de 6500 Threads (em Java), toda a máquina começou a ter problemas e se tornar instável.

Minha experiência mostra que Java (versões recentes) pode consumir felizmente tantos threads quanto o próprio computador pode hospedar sem problemas.

Obviamente, você precisa ter RAM suficiente e ter iniciado o Java com memória suficiente para fazer tudo o que os Threads estão fazendo e ter uma pilha para cada Thread. Qualquer máquina com uma CPU moderna (as mais recentes gerações de AMD ou Intel) e com 1 - 2 Gig de memória (dependendo do SO) pode facilmente suportar uma JVM com milhares de threads.

Se você precisar de uma resposta mais específica que essa, sua melhor aposta é criar um perfil.


86

Hum, muitos.

Existem vários parâmetros aqui. A VM específica, além disso, geralmente há parâmetros de tempo de execução na VM também. Isso é um pouco impulsionado pelo sistema operacional: que suporte o SO subjacente tem para os encadeamentos e quais limitações ele impõe a eles? Se a VM realmente usar encadeamentos no nível do sistema operacional, o bom e velho encadeamento vermelho / verde.

O que significa "suporte" é outra questão. Se você escreve um programa Java que é algo como

   class DieLikeADog {
         public static void main(String[] argv){
             for(;;){
                new Thread(new SomeRunaable).start();
             }
         }
    }

(e não se queixe de pequenos detalhes de sintaxe, estou na minha primeira xícara de café), então você certamente deve esperar centenas ou milhares de threads em execução. Mas criar um Thread é relativamente caro e a sobrecarga do agendador pode ficar intensa; não está claro se você pode fazer com que esses threads façam algo útil.

Atualizar

Ok, não pude resistir. Aqui está o meu pequeno programa de teste, com alguns enfeites:

public class DieLikeADog {
    private static Object s = new Object();
    private static int count = 0;
    public static void main(String[] argv){
        for(;;){
            new Thread(new Runnable(){
                    public void run(){
                        synchronized(s){
                            count += 1;
                            System.err.println("New thread #"+count);
                        }
                        for(;;){
                            try {
                                Thread.sleep(1000);
                            } catch (Exception e){
                                System.err.println(e);
                            }
                        }
                    }
                }).start();
        }
    }
}

No OS / X 10.5.6 na Intel e Java 6 5 (veja comentários), aqui está o que eu recebi

Novo tópico # 2547
Novo tópico # 2548
Novo tópico # 2549
Não é possível criar o tópico: 5
Novo tópico # 2550
Exceção no encadeamento "main" java.lang.OutOfMemoryError: não é possível criar um novo encadeamento nativo
        em java.lang.Thread.start0 (método nativo)
        em java.lang.Thread.start (Thread.java:592)
        em DieLikeADog.main (DieLikeADog.java:6)

10
Com quanta memória você iniciou a JVM? Aquilo importa.
Eddie

10
Java 6 atualização 13, Ubuntu 8.10 32 bits, 4Gig ram, configurações padrão da JVM = 6318 Threads.
Steve K

9
Heh, brinque com o tamanho da pilha de threads. java -Xss100k me permitiu criar threads 19702 no Linux.
Steve K

21
java -Xss50k me levou em torno de 32k threads. Isso maxxed fora meus 4gigs de carneiro embora. Eu tive que interromper alguns processos em execução para recuperar a memória suficiente da minha máquina para bifurcar um novo processo para matar o java;) - bons tempos.
Steve K

21
Usando o Java 7 no Windows 7, criei 200.000 threads antes da morte do meu sistema. O Gerenciador de tarefas mostrou o processo usando 8 GB de RAM. Mas não sei por que parou por aí ... Tenho 12 GB de RAM no meu computador. Portanto, isso pode estar atingindo outro limite.
Dobes Vandermeer

50

Depois de ler a postagem de Charlie Martin, fiquei curioso para saber se o tamanho da pilha faz alguma diferença no número de threads que você pode criar e fiquei totalmente impressionado com o resultado.

Usando o JDK 1.6.0_11 no Vista Home Premium SP1, executei o aplicativo de teste de Charlie com diferentes tamanhos de heap, entre 2 MB e 1024 MB.

Por exemplo, para criar um heap de 2 MB, eu chamaria a JVM com os argumentos -Xms2m -Xmx2m.

Aqui estão meus resultados:

2 mb --> 5744 threads
4 mb --> 5743 threads
8 mb --> 5735 threads
12 mb --> 5724 threads
16 mb --> 5712 threads
24 mb --> 5687 threads
32 mb --> 5662 threads
48 mb --> 5610 threads
64 mb --> 5561 threads
96 mb --> 5457 threads
128 mb --> 5357 threads
192 mb --> 5190 threads
256 mb --> 5014 threads
384 mb --> 4606 threads
512 mb --> 4202 threads
768 mb --> 3388 threads
1024 mb --> 2583 threads

Então, sim, o tamanho da pilha definitivamente importa. Mas a relação entre o tamanho do heap e a contagem máxima de encadeamentos é INVERSAMENTE proporcional.

O que é estranho.


11
faria sentido se cada thread receber um monte desse tamanho.
Thorbjørn Ravn Andersen

1
Advertência: minha máquina não possui 2583 GB de RAM. Ou troque. E a JVM não aloca espaço de pilha local do encadeamento. De modo que não pode ser ele ...
benjismith

49
O tamanho da pilha reduz o espaço de endereço disponível para as pilhas. O espaço de endereço de 256K / pilha faz sentido.
Tom Hawtin - tackline

1

39

Eu sei que esta pergunta é bastante antiga, mas só quero compartilhar minhas descobertas.

Meu laptop é capaz de lidar com programas que aparecem 25,000 threads e todos esses threads gravam alguns dados no banco de dados MySql em intervalos regulares de 2 segundos.

Eu executei este programa com 10,000 threadspor30 minutes continuously , em seguida, também o meu sistema estava estável e eu era capaz de fazer outras operações normais, como navegação, abrir, fechar outros programas, etc.

Com 25,000 threadssistemaslows down mas ele permanece responsivo.

Com o 50,000 threadssistema stopped respondinginstantaneamente e eu tive que reiniciar meu sistema manualmente.

Os detalhes do meu sistema são os seguintes:

Processor : Intel core 2 duo 2.13 GHz
RAM : 4GB
OS : Windows 7 Home Premium
JDK Version : 1.6

Antes de executar, defino o argumento jvm -Xmx2048m.

Espero que ajude.


2
"Diminui a velocidade" soa como troca.
Thorbjørn Ravn Andersen 30/03

Obrigado. Era uma máquina bastante sólida e funcionou bem por quase 8 anos, até que de repente parou de inicializar. Acabei de instalar o Ubuntu nele em vez do Windows e ele começou a analisar números novamente :)
Shekhar

Duo de Fried Core 2 com tempero ubuntu: D
Pasupathi Rajamanickam 09/07/19

31

O máximo teórico absoluto é geralmente o espaço de endereço de usuário de um processo dividido pelo tamanho da pilha de threads (embora, na realidade, se toda a sua memória estiver reservada para pilhas de threads, você não terá um programa de trabalho ...).

Portanto, no Windows de 32 bits, por exemplo, em que cada processo tem um espaço de endereço de usuário de 2 GB, fornecendo a cada thread um tamanho de pilha de 128K, seria de esperar um máximo absoluto de 16384 threads (= 2 * 1024 * 1024/128). Na prática, acho que consigo inicializar cerca de 13.000 no XP.

Então, acho que você quer saber se (a) você pode gerenciar malabarismos com tantos threads em seu código e não fazer coisas obviamente tolas (como fazer com que todos esperem no mesmo objeto e chamar notifyAll () ...), e (b) se o sistema operacional pode. Em princípio, a resposta a (b) é "sim" se a resposta a (a) também é "sim".

Aliás, você pode especificar o tamanho da pilha no construtor do Thread ; você não precisa (e provavelmente não deveria) mexer nos parâmetros da VM para isso.


1
Portanto, use um sistema operacional de 64 bits. Há quanto tempo estamos todos usando processadores de 64 bits?
Tom Hawtin - tackline

Claro, estou apenas dando um exemplo de limite teórico versus prático. Mente-lhe, há uma enorme quantidade de máquinas de 32 bits (incluindo servidores) ainda está lá fora ...
Neil Coffey

2

Lembro-me de ouvir uma conversa de Clojure em que ele executou um de seus aplicativos em uma máquina especializada em uma feira com milhares de núcleos (9000?), E carregou todos eles. Infelizmente, não consigo encontrar o link agora (ajuda?).

Com base nisso, acho seguro dizer que o hardware e seu código são os fatores limitantes, não a JVM.


você poderia olhar de novo? Eu gostaria de vê-lo - parece interessante e suporta que as linguagens funcionais sejam fáceis de dimensionar nos núcleos.
Thorbjørn Ravn Andersen

Você pode fornecer um link para isso? Sei que Cliff Click, Jr., engenheiro líder da Azul Systems, executou a simulação de colônia de formigas de Rich Hickey no maior sistema JCA da Azul (Azul Vega série 3 7300 modelo 7380D: AzulSystems.Com/products/compute_appliance_specs.htm ) com 864 núcleos e 768 GB de RAM e as 700 formigas conseguiram atingir no máximo 700 núcleos. Mas 9000 núcleos, isso é bastante impressionante. Que tipo de máquina era essa?
Jörg W Mittag

Foi a simulação "Formigas" que acredito - aqui está um link em que Rich Hickey (criador do Clojure) fala sobre isso - blip.tv/clojure/clojure-concurrency-819147 . Ele estava em uma grande caixa de sistemas Azul com mais de 800 núcleos, principalmente para demonstrar o quão bom é Clojure no manuseio de simultaneidade de vários núcleos.
Mikera

O @mikera lins expirou.
Thorbjørn Ravn Andersen 30/03

2

Depois de brincar com a classe DieLikeACode de Charlie, parece que o tamanho da pilha de encadeamentos Java é uma grande parte de quantos encadeamentos você pode criar.

-Xss define o tamanho da pilha de threads java

Por exemplo

java -Xss100k DieLikeADog

Mas, Java tem a interface Executor . Eu usaria isso, você poderá enviar milhares de tarefas executáveis ​​e solicitar ao Executor que processe essas tarefas com um número fixo de threads.


13
Podemos chamá-lo de DieLikeACat? não estará morto nem vivo até que você o execute.
Goodwine

Obrigado por apontar para Executors, as pessoas devem usá-lo com mais frequência. Mas não funcionará se o Runnable/ Callablerealmente precisar ser executado continuamente, como quando é necessário lidar com a comunicação. Mas é perfeito para consultas SQL.
Matthieu


0

O número máximo de threads depende do seguinte:

  • Configuração de hardware como microprocessador, RAM.
  • Sistema operacional, seja de 32 ou 64 bits
  • Código dentro do método run. Se o código dentro do método run for enorme, o objeto thread único terá mais requisitos de memória

  • 0

    Informações adicionais para sistemas linux modernos (systemd).

    Existem muitos recursos sobre isso de valores que podem precisar de ajustes (como Como aumentar o número máximo de encadeamentos da JVM (Linux de 64 bits) ); no entanto, um novo limite é imposto por meio do limite do sistema "TasksMax", que define pids.max no cgroup.

    Para sessões de login, o UserTasksMax padrão é 33% do limite do kernel pids_max (geralmente 12.288) e pode ser substituído no /etc/systemd/logind.conf.

    Para serviços, o padrão DefaultTasksMax é 15% do limite do kernel pids_max (geralmente 4.915). Você pode substituí-lo pelo serviço configurando TasksMax em "systemctl edit" ou atualizando DefaultTasksMax em /etc/systemd/system.conf


    0

    Ano de 2017 ... classe DieLikeADog.

    Novo encadeamento # 92459 Exceção no encadeamento "main" java.lang.OutOfMemoryError: não é possível criar um novo encadeamento nativo

    i7-7700 16gb ram


    As respostas fora do curso variam. Eu tenho 10278 com 6 GB de RAM.
    26517 jamie

    -4

    Você pode processar qualquer número de threads; não há limite. Executei o código a seguir enquanto assistia a um filme e usando o NetBeans, e ele funcionou corretamente / sem interromper a máquina. Eu acho que você pode manter ainda mais threads do que este programa.

    class A extends Thread {
        public void run() {
            System.out.println("**************started***************");
            for(double i = 0.0; i < 500000000000000000.0; i++) {
                System.gc();
                System.out.println(Thread.currentThread().getName());
            }
            System.out.println("************************finished********************************");
        }
    }
    
    public class Manager {
        public static void main(String[] args) {
            for(double j = 0.0; j < 50000000000.0; j++) {
                A a = new A();
                a.start();
            }
        }
    }

    7
    Eu sei que esse comentário é muito tarde, mas acredito que a razão pela qual você foi capaz de iniciar e executar esses muitos threads é porque (assumindo configurações normais e razoáveis ​​do sistema) cada thread basicamente imprime uma linha da saída e, em seguida, não tem mais motivos para existe e é eliminado logo depois, garantindo assim uma disponibilidade contínua de recursos.
    ucsunil

    @ucsunil Isso não é verdade. Eu acho que você leu errado o código. Eu apenas tentei e os diferentes threads estão imprimindo não apenas a primeira linha, mas também seus nomes. O que significa que eles estão ativos. Se você pensou que a coleta de lixo reciclará threads não referenciados, isso não acontece, veja aqui .
    Evgeni Sergeev

    1
    No entanto, em pouco tempo, mainlançarei um OutOfMemoryErrorna minha máquina, dizendo que não é possível criar mais threads. Talvez @AnilPal, você não tenha notado isso. Sugiro incluir outra declaração de impressão no main(..)método, para ver claramente quando ele deixa de criar novos threads depois de gerar o erro.
    Evgeni Sergeev

    5
    incrível ... uma descoberta da verdadeira máquina de Turing ... infinitos recursos.
    Josh
    Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
    Licensed under cc by-sa 3.0 with attribution required.