ThreadPoolExecutor - 1

"Os programadores comuns, mais cedo ou mais tarde, se deparam com o fato de que eles têm muitas pequenas tarefas que precisam ser executadas de tempos em tempos."

"Se você está escrevendo um jogo, são as ações que os personagens individuais executam."

"Se você está escrevendo um servidor web, são comandos diferentes vindos dos usuários: fazer upload de uma foto, transcodificá-la no formato desejado, aplicar o modelo desejado, etc."

"Mais cedo ou mais tarde, todas as grandes tarefas são divididas em um conjunto de pequenas tarefas gerenciáveis."

"Portanto, dado esse contexto, surge uma pergunta sutil: como você deve gerenciar todos eles? E se você precisar executar várias centenas de tarefas em um minuto? Criar um thread para cada tarefa não faria muito sentido. A máquina Java aloca muitos recursos para cada thread."

"Em outras palavras, criar e destruir um thread pode levar mais tempo e recursos do que a tarefa em si."

"Os criadores do Java criaram uma solução elegante para esse problema: ThreadPoolExecutor .

" ThreadPoolExecutor é uma classe com duas coisas dentro:"

A)  Uma fila de tarefas, à qual você pode adicionar tarefas conforme elas surgem no programa.

B) Um pool de threads, que é um grupo de threads que executam essas tarefas.

"Além disso, os threads não são destruídos quando uma tarefa é concluída. Em vez disso, eles adormecem para estarem prontos para iniciar uma nova tarefa assim que ela aparecer."

"Ao criar um ThreadPoolExecutor , você pode definir o número máximo de threads a serem criados e o número máximo de tarefas que podem ser enfileiradas. Em outras palavras, você pode limitar o número de threads a 10, por exemplo, e o número de tarefas enfileiradas para 100."

"É assim que o ThreadPoolExecutor funciona:"

1)  Quando você adiciona uma nova tarefa, ela é colocada no final da fila.

2)  Se a fila estiver cheia, uma exceção é lançada.

3)  Ao concluir uma tarefa, cada thread pega a próxima tarefa da fila e começa a executá-la.

4) Se não houver tarefas na fila, uma thread entra em hibernação até que novas tarefas sejam adicionadas.

"A abordagem, em que limitamos o número de threads de trabalho, é vantajosa porque quanto mais threads tivermos, mais eles interferem uns nos outros. É muito mais eficaz ter de 5 a 10 threads de trabalho e uma longa fila de tarefas do que para criar 100 threads para uma onda de tarefas, que irão competir entre si por recursos: memória, tempo de processador, acesso ao banco de dados, etc."

"Aqui está um exemplo de ThreadPoolExecutor em ação:"

Exemplo
ExecutorService service = Executors.newFixedThreadPool(2);

for(int i = 0; i < 10; i++)
{
 service.submit(new Runnable() {
    public void run()
    {
     // Here we download something big from the Internet.
    }
 });
}

"Uh, eu não vejo isso ..."

"Um objeto ThreadPoolExecutor é criado quando o método newFixedThreadPool é chamado."

Então, é muito fácil de usar. Assim que você adicionar uma tarefa a ela com o método submit, ela:

A)  Ativa uma thread adormecida, se houver, para executar a tarefa.

B)  Se não houver thread em espera, ele cria um novo para a tarefa.

C)  Se o número máximo de threads for atingido, ele simplesmente coloca a tarefa no final da fila.

"Incluí deliberadamente «aqui baixamos algo grande da Internet» no exemplo. Se tivermos 100 tarefas «baixar algo grande da Internet», não faz sentido executar muitas delas ao mesmo tempo - nós será retido pelo limite de largura de banda de nossa conexão com a Internet. Nesse caso, alguns threads devem ser suficientes. Isso é o que você vê no exemplo acima:"

ExecutorService service = Executors.newFixedThreadPool(2);

"Acontece que trabalhar com um monte de tarefas não é tão difícil."

"Sim. Ainda mais fácil do que você pode imaginar. Mas Kim vai falar sobre isso."