A partir do Java 5, o Java fornece seu próprio pool de threads. Um pool de threads é um contêiner de rosca, que executa apenas um número nominal de roscas por vez. java.util.concurrent.threadpoolExecutor é um pool de threads. É muito flexível, mas também é complicado de usar, então este artigo o apresentará.
Primeiro é o construtor. Pegue o construtor mais simples como exemplo:
Public ThreadPoolExecutor (int CorePoolSize, int maximumPoolSize, Long KeepaliveTime, Unidade Timeunit, BlockingQueue <Runnable>
Parece bastante complicado. Deixe -me apresentá -lo aqui.
CorePoolSize refere -se ao tamanho do pool de threads reservado.
MaximumPoolSize refere -se ao tamanho máximo do pool de threads.
KeepaliveTime refere -se ao tempo de tempo limite em que o encadeamento ocioso termina.
A unidade é uma enumeração que representa a unidade do KeepaliveTime.
O trabalho de trabalho representa a fila para armazenar tarefas.
Podemos entender o significado desses parâmetros do processo de trabalho do pool de threads. O processo de trabalho do pool de threads é o seguinte:
1. Quando o pool de threads foi criado pela primeira vez, não havia thread dentro. A fila de tarefas é passada como um parâmetro. No entanto, mesmo que haja tarefas na fila, o pool de threads não as executará imediatamente.
2. Ao chamar o método Execute () para adicionar uma tarefa, o pool de threads fará o seguinte julgamento:
a.
b.
c.
d.
3. Quando um thread conclui uma tarefa, é necessário uma tarefa da fila para executar.
4. Quando um thread não tem nada a fazer, e leva um certo tempo (KeepAliveTime), o pool de threads julgará que, se o número de threads em execução estiver maior que o CorePoolSize, o thread será interrompido. Portanto, depois que todas as tarefas do pool de threads são concluídas, ele acabará diminuindo para o tamanho do CorePoolSize.
Esse processo mostra que não é necessário executar a tarefa primeiro se você ingressar na tarefa primeiro. Supondo que o tamanho da fila seja 10, CorePoolSize é 3 e MaximumPoolSize é 6, então quando 20 tarefas são adicionadas, a ordem de execução é a seguinte: Primeiro, as tarefas 1, 2, 3 são executadas e, em seguida, as tarefas 4 ~ 13 são colocadas na fila. Neste momento, a fila está cheia, as tarefas 14, 15, 16 serão executadas imediatamente e as tarefas 17 ~ 20 lançarão exceções. A ordem final é: 1, 2, 3, 14, 15, 16, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13. Aqui está um exemplo de uso do pool de threads:
public static void main (string [] args) {BlockingQueue <dunenable> fila = new LinkedBlockingQueue <duneble> (); 0; out.
Uma explicação deste exemplo é a seguinte:
1. BlockingQueue é apenas uma interface. A vantagem de usar o LinkEdBlockingQueue é que não há limite de tamanho. Dessa forma, porque a fila não estará cheia, o Execute () não lançará uma exceção e o número de threads em execução no pool de threads nunca excederá o CorePoolSize, portanto, o parâmetro KeepaliveTime não tem sentido.
2. O método Shutdown () não bloqueará. Depois de chamar o método Shutdown (), o encadeamento principal termina imediatamente e o pool de threads continuará sendo executado até que todas as tarefas sejam executadas antes de parar. Se o método Shutdown () não for chamado, o pool de threads permanecerá para que novas tarefas possam ser adicionadas a qualquer momento.
Nesse ponto, eu apenas introduzi uma pequena parte deste pool de threads. ThreadpoolExecutor é muito escalável, mas a premissa de estendê -lo é estar familiarizada com a forma como funciona. O artigo a seguir explicará como estender a classe ThreadpoolExector.
A classe Ava.util.Concurrent.ThreadpoolExector fornece extensibilidade rica. Você pode personalizar seu comportamento criando sua subclasse. Por exemplo, quero imprimir uma mensagem após o término de cada tarefa, mas não posso modificar o objeto de tarefas, então posso escrever isso:
ThreadpoolExecutor Executor = novo ThreadPoolExecutor (tamanho, maxSize, 1, TimeUnit.Days, fila) {@Override Protected void AfterExecute (Runnable r, t hrowable t) {System.out.println ("Tarefa finalizada.
Além do método AfterExecute, a classe ThreadPoolExector também possui métodos antes do Execute () e terminou () que podem ser substituídos, que são executados antes que a tarefa seja executada e após o interrupção do pool de threads.
Além de adicionar ações antes e depois que as tarefas sejam executadas, o ThreadPoolExector também permite personalizar a política de execução após a adição de tarefas falhas. Você pode chamar o método setRejecteDexecutionHandler () do pool de threads e substituir a política existente pelo objeto Custom RejejeTexecutionHandler. ThreadpoolExecutor fornece 4 políticas existentes, a saber::
Threadpoolexecutor.abortpolicy: indica que a tarefa é rejeitada e a exceção é jogada
Threadpoolexecutor.discardpolicy: significa rejeitar a tarefa, mas não fazer nenhuma ação
ThreadpoolExecutor.CallERRUNSPOLICY: Indica que a tarefa é rejeitada e a tarefa é executada diretamente no thread do chamador.
ThreadPoolExecutor.DISCARDOLDestPolicy: significa que a primeira tarefa na fila de tarefas é descartada primeiro e, em seguida, a tarefa é adicionada à fila.
Aqui está um exemplo:
ThreadpoolExecutor Executor = new ThreadPoolExecutor (tamanho, maxSize, 1, timeUnit.Days, fila);
Executor.SetRejectEdExecutionHandler (new ThreadPoolExecutor.discardPolicy ());
Além disso, você também pode escrever suas próprias políticas implementando a interface rejejeexecutionhandler. Aqui está um exemplo:
ThreadpoolExector Executor = new ThreadpoolExecutor (3, 6, 1, timeUnit.Segunds, fila, new RejejeexecutionHandler () {public void rejeitExecuti em (Runnable r, threadpoolExector executor) {System.out.println (String.Format (" %DemaskExector render . ", r.hashcode ());}});