O custo de iniciar um encadeamento no sistema é relativamente alto porque envolve interação com o sistema operacional. A vantagem de usar um pool de threads é melhorar o desempenho. Quando o sistema contém um grande número de threads simultâneos, isso causará um declínio acentuado no desempenho do sistema e até faz com que a JVM trava. O número máximo de encadeamentos no parâmetro do pool de threads pode controlar o número de encadeamentos simultâneos no sistema para não exceder o número de vezes.
1. A classe de fábrica de executores é usada para gerar um pool de threads . Esta classe de fábrica contém os seguintes métodos de fábrica estática para criar o pool de threads correspondente. O pool de threads criado é um objeto ExecorService. O método de envio do objeto ou o método executado para executar as tarefas executáveis ou chamáveis correspondentes. O próprio pool de threads chama o método Shutdown () para interromper o pool de threads quando não for mais necessário. Depois de chamar o método, o pool de threads não permitirá mais que as tarefas sejam adicionadas, mas não morrerão até que todas as tarefas adicionadas sejam executadas.
1. NewcachedThreadpool () cria um pool de threads com função de cache e envia o encadeamento criado pela tarefa (objeto executável ou chamável) do pool de threads. Se a execução for concluída, ela será armazenada em cache no cachedThreadpool para uso das tarefas que precisam ser executadas posteriormente.
importar java.util.Concurrent.ExecutorService; importar java.util.concurrent.executores; classe pública Cachethreadpool {classe estática Tarefa implementa Runnable {@Override public void run () {System.out.println (this "" + all -thread.currentTheReads. Thread.currentThread (). GetAllStackTRACES (). Size ()); }} public static void main (string [] args) {ExecutorService Cachethreadpool = executores.newcachedthreadpool (); // Adicione três tarefas ao pool de threads primeiro para (int i = 0; i <3; i ++) {Cachethreadpool.execute (new Task ()); } // Depois que os três threads forem executados, adicione três tarefas ao pool de threads novamente, tente {Thread.sleep (3000); } catch (interruptedException e) {e.printStackTrace (); } para (int i = 0; i <3; i ++) {CacheRreadpool.execute (new Task ()); }}}Os resultados da execução são os seguintes:
Cachethreadpool $ tarefa@2D312EB9 Pool-1-thread-1 AllStacktraces Map Tamanho: 7CachethReadpool $ TASK@59522B86 Pool-1-Thread-3 AllStacktraces Map Tamanho: 7CachethReadpool $ Task@73DBB89F Pool-1-Freread-2TackTackTraCes MapMaMeReReadPool $ Task@73DBB89F Pool-1-TEATHEREAD-TASTACKTACKTRACES MAPA Pool-1-thread-3 AllStacktraces Tamanho do mapa: 7cachethreadpool $ tarefa@256d5600 pool-1-thread-1 allstacktraces mapa tamanho: 7cachethreadpool $ tarefa@7d1c5894 pool-1-thread-2 allstacktraces size: 7 tamanho do mapa: 7
Os objetos de encadeamento no pool de threads são armazenados em cache e reutilizados quando novas tarefas são executadas. No entanto, se houver muita simultaneidade, o pool de threads de cache ainda criará muitos objetos de encadeamento.
2. NewfixedThreadpool (int nthreads) cria um pool de threads com um número especificado de threads que podem ser reutilizados por threads.
importar java.util.concurrent.executorService; importar java.util.concurrent.executores; classe pública FILLTHREADPOOL {classe estática Tarefa implementa Runnable {@Override public void run () {System.out.println (thread + " + thread.CurRentRead (). Thread.currentThread (). GetAllStackTRACES (). Size ()); }} public static void main (string [] args) {ExecutorService fIllThreadpool = executores.newfixedthreadpool (3); // primeiro adiciona três tarefas ao pool de threads para (int i = 0; i <5; i ++) {FILLTHREADPOOL.EXECUTE (new Task ()); } // Depois que os três threads forem executados, adicione três tarefas ao pool de threads novamente, tente {thread.sleep (3); } catch (interruptedException e) {e.printStackTrace (); } para (int i = 0; i <3; i ++) {fixoThreadpool.execute (new Task ()); }}}Resultados da execução:
FIRLETTHREADPOOL $ TASK@7045C12D Pool-1-thread-2 AllStackTRACES Tamanho do mapa: 7FIXEDTHREADPOOL $ TASK@50FA0BEF Pool-1-Thread-2 AllStackTRACS Tamanho do TESTETRADETRADETHEDTHEDTHEAD $ TASK@CCB1870 pool-1-thread-2 AllStackTraces MapMeRead. AllStackTraces Tamanho do mapa: 7FIXEDTHREADPOOL $ TASK@5BDeff18 Pool-1-Thread-2 AllStackTRACES Tamanho do mapa: 7FIXEDTHREADPOOL $ TASK@7D5554E1 Pool-1-Thread-1 AllStackTRACES Tamanho do mapa: 7FIXEDTHREADPOOL $ TASK@24468092 Pool-1-THE 7FIXEDTHREADPOOL $ TASK@FA7B978 Pool-1-Thread-2 AllStacktraces Tamanho do mapa: 7
3. NewsingleThreadExecutor (), crie um pool de threads com apenas threads únicos, o que equivale a chamar newfixedthreadpool (1)
4. NewSheduledThreadpool (int CorePoolSize), cria um pool de threads com um número especificado de threads, que podem executar threads após um atraso especificado. Você também pode repetir um thread em um certo período de tempo, sabendo que pode chamar o desligamento () para fechar o pool de threads.
Exemplos são os seguintes:
import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ScheduledThreadPool { static class Task implements Runnable { @Override public void run() { System.out.println("time " + System.currentTimeMillis() + " " + Thread.currentThread (). GetName () +" AllStacktraces Tamanho do mapa: " + Thread.currentThread (). GetAllStacktraces (). Size ()); }} public static void main (string [] args) {scheduledExecutorService ScheduleDexecutorService = executores.NewsChEduledThreadpool (3); ScheduleDexecutorService.Schedule (new Task (), 3, TimeUnit.Segunds); ScheduleDexecutorService.scheduleatfixedrate (new task (), 3, 5, timeunit.segunds); tente {thread.sleep (30 * 1000); } catch (interruptedException e) {e.printStackTrace (); } scheduledExecutorService.shutdown (); }}Os resultados da operação são os seguintes:
Tempo 1458921795240 Pool-1-thread-1 AllStackTRACES Tamanho do mapa: 6Time 1458921795241 Pool-1-thread-2 AllStacktraces Tamanho do mapa: 6Time 1458921800240 Pool-1-Thread-1-THRACKTRACES Tamanho: 7Time 14589218024240-1-Thread-1-1TackTRACS Tamanho: 14Time 14589218024240-1-Thread-1-1 1458921810240 Pool-1-thread-1 AllStacktraces Tamanho do mapa: 7Time 1458921815240 Pool-1-thread-1 AllStacktraces Tamanho do mapa: 7 Tempo 1458921820240 Pool-1-Thread-1 Allstacktraces Tamanho: 7
Como pode ser visto a partir do tempo de execução, a tarefa é executada em um ciclo de 5 segundos.
5. NewsingleThreadScheduledExecutor () cria um pool de threads com apenas um thread e chama o NewsCheduledThreadpool (1).
2. Forkjoinpool e Forkjointask
O ForkJoinpool é uma classe de implementação do ExecorService. Ele suporta a divisão de uma tarefa em várias pequenas tarefas em computação paralela e combinando os resultados do cálculo de várias pequenas tarefas nos resultados totais de cálculo. Tem dois construtores
ForkJoinpool (int paralelismo) cria um forkjoinpool que contém encadeamentos de paralelismo.
Forkjoinpool (), cria forkjoinpool usando o valor de retorno do método de tempo de execução.
O Forkjointask representa uma tarefa que pode ser paralela e mesclada. É uma classe abstrata que implementa a interface futura <T>. Possui duas subclasses abstratas, representando o recurso recorrente da tarefa sem um valor de retorno e o recursivetask com um valor de retorno. Você pode herdar essas duas classes abstratas de acordo com as necessidades específicas de implementar seus próprios objetos e, em seguida, chamar o método de envio de ForkJoinpool para executar.
O exemplo do recurso recorrente é o seguinte, implementando saídas paralelas de 0-300 números.
importar java.util.concurrent.forkjoinpool; importar java.util.concurrent.recursiveation; importar java.util.Concurrent.TimeUnit; classe pública ActionForkJointask {classe static printTask estende a recursiva {private Static Final Int ThrhShold = 50; Private Int Start; private int end; public printTask (int start, int end) {this.start = start; this.end = end; } @Override Protected void compute () {if (end - start <limles) {for (int i = start; i <end; i ++) {system.out.println (thread.currentThread (). GetName () + "" + i); }} else {int middle = (start + end) / 2; PrintTask esquerdo = new PrintTask (Start, Middle); PrintTask Right = new PrintTask (meio, final); esquerd.fork (); certo.fork (); }}} public static void main (string [] args) {forkjoinpool pool = new forkjoinpool (); Pool.submit (New PrintTask (0, 300)); tente {Pool.awaitmining (2, timeUnit.SECONDS); } catch (interruptedException e) {e.printStackTrace (); } pool.shutdown (); }}Depois de dividir a pequena tarefa, chame o método Fork () da tarefa e adicione -o ao ForkJoinpool para execução em paralelo.
Exemplo de Recursivetask, implementa o cálculo paralelo de 100 números inteiros para soma. Divida em todos os 20 números e resista a obter o resultado e mescle -os no resultado final no final.
importar java.util.random; importar java.util.concurrent.executionException; importar java.util.concurrent.forkJoinpool; importar java.util.Concurrent.Future; Import Java.util.Concurrent.RecursTask; limite final estático privado INT = 20; private int arr []; Private Int Start; private int end; public CalTask (int [] arr, int start, int end) {this.arr = arr; this.start = start; this.end = end; } @Override Protected integer compute () {int sum = 0; if (end - start <limiar) {for (int i = start; i <end; i ++) {sum+= arr [i]; } System.out.println (thread.currentThread (). GetName () + "sum:" + soma); soma de retorno; } else {int middle = (start + end) / 2; Caltask esquerda = new CalTask (arr, start, meio); Caltask Right = New CalTask (arr, meio, final); esquerd.fork (); certo.fork (); retornar esquerda.Join () + Right.Join (); }}} public static void main (string [] args) {int arr [] = new int [100]; Aleatório aleatório = novo aleatório (); int total = 0; for (int i = 0; i <arn.length; i ++) {int tmp = aleatom.nextInt (20); total += (arr [i] = tmp); } System.out.println ("Total" + Total); Pool ForkJoinpool = New ForkJoinpool (4); Futuro <Teger> futuro = pool.submit (novo caltask (arr, 0, arr.length)); tente {System.out.println ("Resultado cal:" + futura.get ()); } catch (interruptedException e) {e.printStackTrace (); } catch (executionException) e) {e.printStackTrace (); } pool.shutdown (); }}Os resultados da execução são os seguintes:
total 912ForkJoinPool-1-worker-2 sum:82ForkJoinPool-1-worker-2 sum:123ForkJoinPool-1-worker-2 sum:144ForkJoinPool-1-worker-3 sum:119ForkJoinPool-1-worker-2 sum:106ForkJoinPool-1-worker-2 sum:128ForkJoinPool-1-worker-2 Soma: 121forkJoinpool-1-Worker-3 Soma: 89Cal Resultado: 912
Depois que a subtarefa for executada, ligue para o método junção () da tarefa para obter o resultado da execução da subtarefa e adicione -o para obter o resultado final.