Tenho um programa que gera threads (~ 5-150) que realizam várias tarefas. Originalmente, usei um FixedThreadPool
porque essa pergunta semelhante sugeria que eles eram mais adequados para tarefas de longa duração e, com meu conhecimento muito limitado de multithreading, considerei a vida média dos threads (vários minutos) de " vida longa ".
No entanto, recentemente adicionei a capacidade de gerar threads adicionais e isso me leva acima do limite de threads que defini. Nesse caso, seria melhor adivinhar e aumentar o número de encadeamentos que posso permitir ou alternar para um CachedThreadPool
para que não tenha encadeamentos desperdiçados?
Experimentando os dois preliminarmente, não parece haver diferença, então estou inclinado a ir com o CachedThreadPool
apenas para evitar o desperdício. No entanto, a vida útil dos fios significa que, em vez disso, devo escolher um FixedThreadPool
e apenas lidar com os fios não utilizados? Esta pergunta faz parecer que esses tópicos extras não foram desperdiçados, mas agradeceria o esclarecimento.
ThreadPoolExecutor
gosto limitadoThreadPoolExecutor(0, maximumPoolSize, 60L, TimeUnit.SECONDS, SynchronousQueue())
?Ambos
FixedThreadPool
eCachedThreadPool
são males em aplicativos altamente carregados.CachedThreadPool
é mais perigoso queFixedThreadPool
Se seu aplicativo estiver altamente carregado e exigir baixa latência, é melhor se livrar de ambas as opções devido às desvantagens abaixo
CachedThreadPool
Threads de longa execução irão causar a perda de controle na criação de threadsJá que você sabe que ambos são males, o mal menor não faz bem. Prefira ThreadPoolExecutor , que fornece controle granular em muitos parâmetros.
beforeExecute(Thread, Runnable)
eafterExecute(Runnable, Throwable)
fonte
Tem certeza de que entende como os threads são realmente processados pelo seu sistema operacional e hardware de escolha? Como Java mapeia threads para threads de SO, como isso mapeia threads para threads de CPU etc.? Estou perguntando porque a criação de 150 threads em ONE JRE só faz sentido se você tiver núcleos / threads de CPU massivos por baixo, o que provavelmente não é o caso. Dependendo do sistema operacional e da RAM em uso, a criação de mais de n threads pode até mesmo resultar no encerramento do JRE devido a erros de OOM. Portanto, você realmente deve distinguir entre os threads e o trabalho a fazer por esses threads, quantos trabalhos você é capaz de processar, etc.
E esse é o problema com CachedThreadPool: não faz sentido enfileirar trabalhos de longa execução em threads que na verdade não podem ser executados porque você só tem 2 núcleos de CPU capazes de processar essas threads. Se você terminar com 150 threads agendados, poderá criar muita sobrecarga desnecessária para os agendadores usados no Java e no sistema operacional para processá-los simultaneamente. Isso é simplesmente impossível se você tiver apenas 2 núcleos de CPU, a menos que seus threads estejam esperando por E / S ou algo parecido o tempo todo. Mas mesmo nesse caso, muitos encadeamentos criariam muito I / O ...
E esse problema não ocorre com FixedThreadPool, criado com, por exemplo, 2 + n threads, onde n é razoavelmente baixo, é claro, porque com esse hardware e os recursos do sistema operacional são usados com muito menos sobrecarga para gerenciar threads que não podem ser executados de qualquer maneira.
fonte