ThreadPoolExecutor com corePoolSize 0 não deve executar tarefas até que a fila de tarefas esteja cheia
Eu estava passandoConcorrência Java na prática e ficou preso no8.3.1 Criação e desmontagem de encadeamentos tema. A nota de rodapé a seguir alerta sobre como mantercorePoolSize
para zero.
Às vezes, os desenvolvedores são tentados a definir o tamanho do núcleo como zero, para que os encadeamentos do trabalhador acabem sendo reduzidos e, portanto, não impedem a saída da JVM, mas isso pode causar um comportamento aparentemente estranho nos conjuntos de encadeamentos que não usam um SynchronousQueue para sua fila de trabalho (como newCachedThreadPool faz).Se o pool já estiver no tamanho principal, ThreadPoolExecutor criará um novo thread apenas se a fila de trabalho estiver cheia. Portanto, as tarefas enviadas para um conjunto de encadeamentos com uma fila de trabalho com capacidade e tamanho de núcleo zero não serão executadas até que a fila seja preenchida, que geralmente não é o desejado.
Então, para verificar isso, escrevi este programa que não funciona como mencionado acima.
final int corePoolSize = 0;
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
// If the pool is already at the core size
if (tp.getPoolSize() == corePoolSize) {
ExecutorService ex = tp;
// So tasks submitted to a thread pool with a work queue that has any capacity
// and a core size of zero will not execute until the queue fills up.
// So, this should not execute until queue fills up.
ex.execute(() -> System.out.println("Hello"));
}
Resultado: Olá
Então, o comportamento do programa sugere queThreadPoolExecutor
cria pelo menos um encadeamento se uma tarefa for enviada independentemente decorePoolSize=0
. Se sim, qual é o aviso no livro de texto.
EDITAR: Testou o código emjdk1.5.0_22 sob a sugestão de @ S.K. com a seguinte alteração:
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(1));//Queue size is set to 1.
Mas com essa alteração, o programa termina sem imprimir nenhuma saída.
Então, estou interpretando mal essas afirmações do livro?
EDIT (@sjlee): É difícil adicionar código no comentário, por isso vou adicioná-lo como uma edição aqui ... Você pode experimentar essa modificação e executá-la no JDK e no JDK 1.5 mais recentes?
final int corePoolSize = 0;
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// If the pool is already at the core size
if (tp.getPoolSize() == corePoolSize) {
ExecutorService ex = tp;
// So tasks submitted to a thread pool with a work queue that has any capacity
// and a core size of zero will not execute until the queue fills up.
// So, this should not execute until queue fills up.
ex.execute(() -> System.out.println("Hello"));
}
tp.shutdown();
if (tp.awaitTermination(1, TimeUnit.SECONDS)) {
System.out.println("thread pool shut down. exiting.");
} else {
System.out.println("shutdown timed out. exiting.");
}
@sjlee Postou o resultado nos comentários.