Prefácio
Os artigos anteriores se concentram na otimização do banco de dados de serviço de back-end e no processamento paralelo com vários threads e exemplos de lógica pseudocode antes e após a transformação. Obviamente, a otimização é interminável. As gerações anteriores plantam árvores e as gerações posteriores desfrutam da sombra. Como desenvolvedores, como estamos sobre os ombros dos gigantes, devemos escrever programas mais otimizados.
Caso de desenvolvimento de trampolim JDBCTemplate Operação em lote
Caso de desenvolvimento de trampolim: processamento de processamento paralelo multitarefa de contagem regressiva
Renovação
Teoricamente, quanto mais threads, mais rápido será o programa, mas, no uso real, precisamos considerar o consumo de recursos da própria criação e destruição do encadeamento, bem como o objetivo de proteger o próprio sistema operacional. Normalmente, precisamos limitar os threads a um determinado intervalo, e os pools de threads desempenham esse papel.
Lógica do programa
Paralelo multitarefa + processamento de pool de threads.png
Os problemas que podem ser resolvidos por uma imagem devem ser o mínimo possível. Obviamente, o princípio subjacente ainda precisa ser lembrado e compreendido por todos.
Java Thread Pool
Java fornece quatro tipos de pools de threads através de executores, a saber:
vantagem
Implementação de código
Método 1 (CountdownLatch)
/*** Paralelo de multitarefa + estatísticas do pool de thread* Tempo de criação 17 de abril de 2018*/public classe statsdemo {final estático simpledateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); Final Static String InictTime = sdf.format (new Date ()); / ** * Tarefas intensivas em IO = geralmente 2 * Número de núcleos da CPU (geralmente em threads: interação de dados do banco de dados, upload e download de arquivos, transmissão de dados de rede, etc.) * Tarefas intensivas em CPU = geralmente 1 Cores de CPU + 1 (frequentemente em linhas: algoritmos complexos) * Hybrid Tasks = dependendo a oneração da máquina + 1 RUNTIME.GETRUNTIME (). DISPONÍVELPROCESSORS (); /*** Public ThreadPoolExecutor (int CorePoolSize, Int MaximumPoolSize, Longo KeepAliveTime,* Unidade TimeUnit, BlockingQueue <uncrnable> WorkQueue)* CorePoolSize é usado para especificar o número de threads* maximumpoolsize especifica o número máximo de o tempo de manutenção e o tempo, o número de threads* o shusts* especifica o número máximo de threads e o tempo, o número de threads* shiftiTeUn SsenheUn SsenheUn, o número máximo de threads*, o número de threads* shusts* shiftiTeUn SsenheUn SsenheUn Ssenhe, o número máximo de threads* A fila do pool de threads e os threads que ainda não foram executados aguardam na fila* Monitore o comprimento da fila para garantir que a fila limitada* tamanho inadequado do pool de encadeamentos possa diminuir a velocidade do processamento, reduzir a estabilidade e levar ao vazamento de memória. Se houver poucos threads configurados, a fila continuará a crescer e consumir muita memória. * E muitos threads diminuem a velocidade de todo o sistema devido à comutação de contexto frequente - e o mesmo resultado final será alcançado. O comprimento da fila é crucial, ela deve ser delimitada para que, se o pool de threads estiver sobrecarregado, poderá rejeitar temporariamente novas solicitações. * A implementação padrão do ExecutorService é um LinkedBlockEue não limitado. */ Private Static ThreadPoolExector Executor = new ThreadPoolExecutor (CorePoolSize, CorePoolSize+1, 10L, TimeUnit.Seconds, novo LinkedBlockingQueue <dunnable> (1000)); public static void main (string [] args) lança interruptedException {Countdownlatch Latch = new Countdownlatch (5); // Use o método Execute Execoror.execute (novas estatísticas ("Tarefa A", 1000, trava)); executor.execute (novas estatísticas ("Tarefa B", 1000, trava)); executor.execute (novas estatísticas ("Tarefa C", 1000, trava)); executor.execute (novas estatísticas ("Task d", 1000, trava)); executor.execute (novas estatísticas ("Tarefa e", 1000, trava)); latch.await (); // Aguarde a tarefa de todos os encerrar o sistema.out.println ("Todas as tarefas estatísticas são concluídas:" + sdf.format (new Date ())); } classe estática estatísticas implementa Runnable {String statsName; int tempo de execução; Countdownlatch Latch; Estatísticas públicas (String statsName, int RunTime, CountdownLatch Latch) {this.statsName = statsName; this.Runtime = Runtime; this.latch = latch; } public void run () {try {System.out.println (statsName+ "do sTATS começa no"+ startTime); // simular thread de tempo de execução de tarefas.sleep (tempo de execução); System.out.println (STATSNAME + "DO ESTATAS COMPLETAS em" + sdf.format (new Date ())); latch.countdown (); // uma única tarefa termina, o contador é reduzido por um} catch (interruptedException e) {e.printStackTrace (); }}}}Método 2 (futuro)
/*** Paralelo de multitarefa + estatísticas do pool de thread* Tempo de criação 17 de abril de 2018*/public classe statsdemo {final estático simpledateFormat sdf = new SimpleDateFormat ("yyyy-mm-dd hh: mm: ss"); Final Static String InictTime = sdf.format (new Date ()); / ** * Tarefas intensivas em IO = geralmente 2 * Número de núcleos da CPU (geralmente em threads: interação de dados do banco de dados, upload e download de arquivos, transmissão de dados de rede, etc.) * Tarefas intensivas em CPU = geralmente 1 Cores de CPU + 1 (frequentemente em linhas: algoritmos complexos) * Hybrid Tasks = dependendo a oneração da máquina + 1 RUNTIME.GETRUNTIME (). DISPONÍVELPROCESSORS (); /*** Public ThreadPoolExecutor (int CorePoolSize, Int MaximumPoolSize, Longo KeepAliveTime,* Unidade TimeUnit, BlockingQueue <uncrnable> WorkQueue)* CorePoolSize é usado para especificar o número de threads* maximumpoolsize especifica o número máximo de o tempo de manutenção e o tempo, o número de threads* o shusts* especifica o número máximo de threads e o tempo, o número de threads* shiftiTeUn SsenheUn SsenheUn, o número máximo de threads*, o número de threads* shusts* shiftiTeUn SsenheUn SsenheUn Ssenhe, o número máximo de threads* A fila do pool de threads e os threads que ainda não foram executados aguardam na fila* Monitore o comprimento da fila para garantir que a fila limitada* tamanho inadequado do pool de encadeamentos possa diminuir a velocidade do processamento, reduzir a estabilidade e levar ao vazamento de memória. Se houver poucos threads configurados, a fila continuará a crescer e consumir muita memória. * E muitos threads diminuem a velocidade de todo o sistema devido à comutação de contexto frequente - e o mesmo resultado final será alcançado. O comprimento da fila é crucial, ela deve ser delimitada para que, se o pool de threads estiver sobrecarregado, poderá rejeitar temporariamente novas solicitações. * A implementação padrão do ExecutorService é um LinkedBlockEue não limitado. */ Private Static ThreadPoolExector Executor = new ThreadPoolExecutor (CorePoolSize, CorePoolSize+1, 10L, TimeUnit.Seconds, novo LinkedBlockingQueue <dunnable> (1000)); public static void main (string [] args) lança interruptedException {list <futuro <string>> resultList = new ArrayList <FUTTURA <String>> (); // Use Envie uma tarefa assíncrona e obtenha o valor de retorno como Future ResultList.add (Executor.submit (New Stats ("Task A", 1000))); resultList.add (Executor.submit (novas estatísticas ("Tarefa B", 1000))); resultadolist.add (executor.submit (novas estatísticas ("Tarefa C", 1000))); resultadolist.add (executor.submit (novas estatísticas ("tarefa d", 1000))); resultadolist.add (executor.submit (novas estatísticas ("Tarefa E", 1000))); // resultado da tarefa Traversal para (Future <string> fs: resultList) {try {System.out.println (fs.get ()); // imprima os resultados de cada execução de tarefas de linha, ligue para o futuro.get (intercepedException e) e obtenha o resultado do retorno do sholronstring} (intercepedException e) {e obtenha o resultado do sholronstring}; } catch (ExecutionException e) {e.printStackTrace (); } finalmente {// inicie uma vez e execute as tarefas enviadas anteriormente, mas não aceite novas tarefas. Se foi fechado, a chamada não tem outro efeito. executor.shutdown (); }} System.out.println ("Todas as tarefas estatísticas são executadas:" + sdf.format (new Date ())); } classe estática estatísticas implementa Callable <String> {String statsName; int tempo de execução; Public Stats (String statsName, int RunTime) {this.statsName = statsName; this.Runtime = Runtime; } public string Call () {try {System.out.println (statsName+ "do STATS começa no"+ startTime); // simular thread de tempo de execução de tarefas.sleep (tempo de execução); System.out.println (STATSNAME + "DO ESTATAS COMPLETAS em" + sdf.format (new Date ())); } catch (interruptedException e) {e.printStackTrace (); } retornar chamada (); }}}Tempo de execução
Os códigos acima são todos pseudo-códigos, e os seguintes são reais registros de teste de mais de 2.000 alunos.
2018-04-17 17: 42: 29.284 Registro de teste de informações 81E51AB031EB4ADA92743DDF666528D82 Execução seqüencial-t-threaded-thread, tempo gasto: 3797
2018-04-17 17: 42: 31.452 Registro de teste de informações 81E51AB031EB4ADA92743DDF666528D82-MULTI-THELLED Tarefa, tempo gasto: 2167
2018-04-17 17: 42: 33.170 Registro de teste de informações 81E51AB031EB4ADA92743DDF666528D82 MULTIMA-MULT-THRELED TARELA + POOL
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.