Duas maneiras de implementar o pool de threads em Java

01 Cenários de aplicativos do conjunto de encadeamentos

(1) aplicação

Por exemplo, o software de retoque atual na coleção. Uma imagem 1920 x 1080 tem mais de 2 milhões de pixels e é preciso muito cálculo para processar cada pixel da imagem inteira.

(2) Lado do servidor

Quando o lado do servidor processa big data e um grande número de solicitações, se for apenas um encadeamento, ele não pode atender à demanda.

Além disso, independentemente de estar processando aplicativos ou servidores, mesmo se vários threads forem usados, se os threads forem criados e destruídos frequentemente, o tempo final de criação e destruição poderá ser maior que o tempo real de execução. Reutilizar objetos é uma boa opção, para que você possa escolher um pool de threads.

As classes Java comumente usadas envolvidas no conjunto de encadeamentos incluem ThreadPoolExecutor, Executors, etc.

02 ThreadPoolExecutor

(1) O ThreadPoolExecutor é mais complicado para criar objetos.A figura a seguir mostra vários construtores fornecidos no JDK 11.

Esses parâmetros envolvem principalmente a configuração de alguns parâmetros principais do conjunto de encadeamentos. Tome o construtor com mais parâmetros como exemplo:

public ThreadPoolExecutor(int corePoolSize, 
													int maximumPoolSize, 
													long keepAliveTime, 
													TimeUnit unit, 
													BlockingQueue<Runnable> workQueue, 
													ThreadFactory threadFactory, 
													RejectedExecutionHandler handler) {
	...
}
复制代码

corePoolSize O número de encadeamentos salvos no conjunto de encadeamentos quando ocioso.

maximumPoolSize O número máximo de encadeamentos permitido no conjunto de encadeamentos.

keepAliveTime Quando houver encadeamentos inativos, e o número de encadeamentos existentes for maior que corePoolSize, o encadeamento será excluído após o tempo especificado e o encadeamento não será excluído dentro do tempo especificado.

unit Refere-se à unidade de tempo definida de keepAliveTime.

workQueue Usado para salvar a fila de tarefas antes da execução.

threadFactory Especifica a classe de fábrica para criar threads personalizados.

handler O objetivo de RejectedExecutionHandler é implementar algum processamento quando tarefas são adicionadas após o fechamento do conjunto de encadeamentos, como registrar as informações de encadeamento rejeitadas.

(2) métodos execute () e submit ()

Ambos podem enviar tarefas como um pool de threads, mas os detalhes serão diferentes.

execute()Você pode adicionar uma tarefa, mas o tipo só pode ser executável e a tarefa não pode retornar resultados. Quando uma exceção de thread automático é encontrada, as informações da exceção são impressas diretamente e o thread principal não pode capturar as informações da exceção.

submit()Você pode adicionar uma tarefa, mas retornar um objeto Future e obter o resultado retornado através de Future. Quando uma exceção é encontrada, as informações da exceção podem ser capturadas no encadeamento principal.

Os parâmetros do método submit () envolvem dois tipos de interfaces de chamada e Runnable, e suas principais diferenças são:

(A) O método call () da interface Callable pode ter um valor de retorno, enquanto o método run () da interface Runnable não tem valor de retorno.

(B) O método call () da interface Callable pode gerar uma exceção por toda a vida, enquanto o método run () da interface Runnable não pode declarar uma exceção.

(3) Outros métodos comuns

shutdown() O thread principal termina imediatamente e não bloqueia. O thread no pool de threads para execução continuará sendo executado. Nenhuma nova tarefa será adicionada ao pool de threads.O pool de threads continuará sendo executado até que todos os threads tenham concluído a execução.

Quando o encadeamento programará imediatamente o estado SHUTDOWN, no momento, não será mais necessário adicionar Tarefa ao conjunto de encadeamentos; caso contrário, ative a exceção RejectedExecutionException.

shutdownNow()Interrompa todas as tarefas e ative InterruptException. Imediatamente após a execução, ele entra no estado STOP e tenta parar todos os threads em execução, e não processa mais tarefas que ainda estão aguardando no conjunto de threads.

Após a execução deste método, ele retornará as tarefas não executadas: List

isShutdown() Determine se o conjunto de encadeamentos foi fechado.

isTerminating() Retorna true se estiver em processo de rescisão.

isTerminated() Julgue que todas as tarefas foram concluídas.

awaitTermination() Verifique se o conjunto de encadeamentos encerrou o trabalho dentro do tempo especificado.

03 Executores

Executors é uma classe de criação de conjuntos de encadeamentos que pode facilitar a criação de conjuntos de encadeamentos através dos métodos já fornecidos.

(1) Métodos comuns fornecidos pelos Executores:

newCachedThreadPool() Crie um conjunto de encadeamentos ilimitado, que pode reciclar automaticamente os segmentos.O chamado "conjunto máximo de encadeamentos" é o valor máximo teórico do número de encadeamentos armazenados no conjunto e o valor máximo de Integer.MAX_VALUE.

newCachedThreadPool(ThreadFactory) Encadeamentos em um conjunto de encadeamentos personalizado

newFixedThreadPool(int) Criar um conjunto de threads limitados

newFixedThreadPool(int, ThreadFactory) Crie um conjunto de threads limitados de threads personalizados.

newSingleThreadExector() Crie um único conjunto de encadeamentos para implementar tarefas em uma fila.

newSingleThreadExecutor() Crie um conjunto de threads único com uma fábrica.

04 Case

(1) Use ThreadPoolExecutor para criar um pool de threads

package com.page.concurrent.pool;

import java.util.concurrent.*;

public class Game {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        		1, 2, 1000 * 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>());

        Future<String> future = threadPoolExecutor.submit(() -> {
            System.out.println("Should work 4 seconds.");
            Thread.sleep(1000 * 4);
            System.out.println("Work done.");
            return "OK";
        });

        String result = future.get();
        System.out.println("Thread response result is " + result);
        threadPoolExecutor.shutdownNow();
        System.out.println("Thread pool status: isShutdown=" + threadPoolExecutor.isShutdown());
        Thread.sleep(1000 * 5);
        System.out.println("Thread pool status: isTerminated" + threadPoolExecutor.isTerminated());
    }
}

复制代码

(2) Use Executors para criar um pool de threads

O que outras pessoas estão dizendo

package com.page.concurrent.pool;

import java.util.concurrent.*;

public class Game {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();

        Future<String> future = executorService.submit(() -> {
            System.out.println("Should work 4 seconds.");
            Thread.sleep(1000 * 4);
            System.out.println("Work done.");
            return "OK";
        });

        String result = future.get();
        System.out.println("Thread response result is " + result);
        executorService.shutdownNow();
        System.out.println("Thread pool status: isShutdown=" + executorService.isShutdown());
        Thread.sleep(1000 * 5);
        System.out.println("Thread pool status: isTerminated" + executorService.isTerminated());
    }
}

复制代码

Acho que você gosta

Origin juejin.im/post/5e9830c4518825738c3648c9
Recomendado
Clasificación