Eu tenho um programa java que escuta em uma porta para entrada. Com base na entrada, ele chama um serviço da web e retorna um sucesso / falha de volta ao programa cliente.
Eu bifurco um fio para cada conexão do cliente. A resposta de volta ao cliente que se conecta ao programa deve ser rápida.
Essas são as escolhas que estou considerando
- use threads regulares
- use
ExecutorService
comnewFixedThreadPool
- use
ExecutorService
comnewCachedThreadPool
A razão pela qual estou considerando Pools é porque meus threads têm vida curta - eles apenas chamam um serviço da web, retornam o resultado ao cliente e fecham a conexão.
Eu não acho newFixedThreadPool
que seria a coisa certa, porque então as conexões estariam esperando nas filas para obter um encadeamento.
newCachedThreadPool
teria sido perfeito, exceto por uma coisa - os fios morrem depois de um minuto. No meu caso, recebo rajadas de conexões - ou seja, várias conexões e, em seguida, pode haver uma pausa por alguns minutos e, novamente, rajadas. Eu acho que os threads no CachedThreadPool morrem e precisam ser recriados novamente - portanto, nesse caso, pode funcionar como o número 1 às vezes.
Idealmente, eu adoraria ter newCachedThreadPool
um mínimo - ou seja, uma configuração que diz que o número de threads nunca ficaria abaixo da palavra 20. Assim, os threads inativos são eliminados, mas nunca permitem que eles fiquem abaixo de um limite mínimo.
Existe algo assim disponível? Ou existem alternativas melhores?
fonte
Respostas:
Os métodos na classe Executors são apenas métodos de conveniência para casos de uso comuns. Há muito mais opções disponíveis para a criação de conjuntos de encadeamentos.
Para criar a mesma coisa que Executors.newCachedThreadPool () faz, mas com um mínimo de 20 threads (isso é copiado do método em Executors, com o tamanho do thread principal alterado de 0 para 20).
fonte
Pergunta interessante.
Eu recomendaria contra
newCachedThreadPool
. Irá gerar quantos threads forem necessários, sem nenhum limite superior. Isso é ruim!A abordagem sugerida por Michael parece boa. Use
ThreadPoolExecutor
e use um número com o qual você se sinta confortável como o tamanho do pool principal. Defina o número máximo de threads para algo que você deseja tolerar (ou seu servidor pode manipular).Observe que não há praticamente nada que você possa fazer quando esgotar o recurso (a fila está cheia e o número máximo de threads está funcionando). Nesse caso, você pode fazer uma das duas coisas: descartar novas conexões ou aplicar contrapressão (não aceite novos trabalhos bloqueando). Por padrão, o TPE lança
RejectedExecutionException
quando está cheio, mas é fácil implementar o comportamento de bloqueio. De fato, aqui está uma implementação de código aberto do BlockingThreadPoolExecutor .fonte
Em relação à RejectedExecutionException:
Em vez de um BlockingThreadPoolExecutor, podemos simplesmente definir o RejectedExecutionHandler no ThreadPoolExecutor para usar o manipulador CallerRunPolicy .
fonte
Eu acho que usar um invólucro sobre um ThreadPoolExecutor é um bom caminho a percorrer. Um wrapper para que você possa expor alguma inicialização (como um nome de pool, número de threads, etc.) e um método para adicionar uma tarefa (Runnable) a um pool criado anteriormente com um dos métodos init.
O wrapper pode alterar o pool usado sem afetar outro código, além de expor outros métodos como número de threads, auditorias (tarefa antes / depois) de maneira consistente
Você também pode implementar sua própria fábrica de Threads para seu pool, que pode ter um nome personalizado, prioridade e, no mínimo, gancho em um UncaughtExceptionHandler para poder registrar erros.
no meu invólucro de piscina, temos métodos como
fonte