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.

questionAnswers(2)

yourAnswerToTheQuestion