Recentemente, encontrei um novo requisito no projeto, que é implementar uma função que pode adicionar dinamicamente tarefas cronometradas. Falando nisso, algumas pessoas podem dizer que é simples, basta usar quartzo, é simples e grosseiro. No entanto, a estrutura do quartzo é muito pesada e pequenos projetos não são fáceis de operar. Obviamente, algumas pessoas podem dizer que o JDK fornece interface do timer, o que é completamente suficiente. No entanto, os requisitos do nosso projeto são modelos completamente multithread, enquanto o timer é um único thread, e o autor finalmente escolheu o pool de threads do JDK.
O que é um pool de threads
Java fornece quatro tipos de pools de threads através de executores, a saber:
NewcachedThreadpool: Crie um pool de threads em cache. Se o comprimento do pool de threads exceder as necessidades de processamento, você poderá reciclar de forma flexível encadeamentos ociosos. Se não houver reciclagem, crie um novo thread.
NewFixedThreadpool: cria um pool de encadeamentos de comprimento fixo que pode controlar o número máximo de simultaneidade de threads, e os threads em excesso aguardam na fila.
NewscheduledThreadpool: cria um pool de threads de comprimento fixo que suporta a execução de tarefas cronometradas e periódicas.
NewsingleThreadExecutor: cria um pool de threads de thread único, que usará apenas um thread de trabalhador exclusivo para executar tarefas, garantindo que todas as tarefas sejam executadas na ordem especificada (FIFO, LIFO, prioridade).
O pôster usa o NewsCheduledThreadpool no projeto. Isso é tudo. Não importa quantos pôsteres você seja, você exibirá suas habilidades. Google e é muito.
Obtendo serviço de pool de threads
O autor usa o modo Singleton para obter o serviço do pool de threads. O código é o seguinte:
/*** Criação do pool de threads. * @author wuhf * @date 2018/01/16 */public class ThreadPoolUtils {private Static ScheduleDexecutorService ExecorService; Private ThreadPoolUtils () {// Crie manualmente o pool de threads. executorService = new ScheduledThreadpoolExecutor (10, new BasicThreadFactory.Builder (). NamingPattern ("SyncData-schedule-pool-%d"). Daemon (true) .build ()); } classe estática privada pluginconfigholder {private final estático threadpoolutils instance = new threadpoolutils (); } public static threadpoolUtils getInstance () {return pluginconfigholder.instance; } public ScheduleDexecutorService getThreadpool () {return ExecutSerService; }}Interrompendo uma implementação de código de threads em execução
Não vou dizer muita bobagem, o código é o seguinte:
/*** Uma tarefa no pool de threads é interrompida. */public class Interruptthread implementa Runnable {private int num; public interruptThread (int num) {this.num = num; } public static void main (string [] args) lança interruptedException {thread interruptThread = new Thread (new interruptThread (1)); Agendadofuture <?> T = threadpoolutils.getInstance (). GetThreadpool (). Scheduleatfixedrate (interruptthread, 0,2, timeunit.seconds); Interruptthread interruptThread1 = new interruptThread (2); Threadpoolutils.getInstance (). GetThreadpool (). Scheduleatfixedrate (interruptThread1,0,2, timeunit.seconds); Interruptthread interruptThread2 = new interruptThread (3); Threadpoolutils.getInstance (). GetThreadpool (). ScheduleAtFixedrate (interruptThread2,0,2, timeUnit.Seconds); Thread.sleep (5000); // encerrar o thread em execução InterruptThread T.Cancel (true); while (true) {}} @Override public void run () {System.out.println ("Este é um thread" + num); }}Registro preso
Quando o pôster estava usando o código a seguir, ele de repente pensou em como impedir que o tópico seja executado quando essa tarefa de tempo precisa ser interrompida.
Threadpoolutils.getInstance (). GetThreadpool (). Scheduleatfixedrate (interruptThread, 0,2, timeunit.seconds);
Como eu tenho tanta necessidade, vamos pesquisar no Google. Depois de procurar a maior parte do tempo, não consegui encontrar nenhuma informação relevante. Eles eram todos análises detalhadas do pool de threads Java. Ou variáveis globais ou algo assim, nenhuma solução foi encontrada para satisfazer o autor.
Como não há thread, vamos dar uma olhada no código -fonte subjacente do ScheduleAtFixedrate para ver o que é. Como esperado, vi a implementação específica do método ScheduleatFixedrate no código -fonte e descobri que seu valor de retorno está agendado.
public ScheduledFuture <?> scheduleatfixedrate (comando runnable, long InitialDelay, longo período, unidade de unidade de tempo) {if (command == null || unit == null) lança new nullPointerException (); if (período <= 0) lançar novo ilegalargumentException (); Agendada de FutureTask <Void> sft = new ScheduledFutureTask <Void> (comando, nulo, TrigGerTime (InitialDelay, Unit), Unit.tonanos (Período)); Runnablescheduledfuture <Void> t = decorateTask (comando, sft); sft.outerTask = t; touchedExExecute (t); retornar t; }Então, vamos dar uma olhada no que está dentro do Future ScheduledFuture. Não decepcionou o pôster, e eu vi isso
public boolean cancel (boolean mayInterruptifrunning) {boolean cancelado = super.cancel (MayInterruptifrunning); if (cancelado && removeOnCancel && heapIndex> = 0) remover (this); Retornar cancelado;} // Remova o encadeamento atual da fila em execução Public boolean Remover (Runnable Task) {boolean Removed = WorkQueUe.Remove (Task); tryMermAminate (); // no caso de desligamento e agora o retorno vazio removido;}Vamos verificar o que é super.cancel (MayInterruptifrunning). Nós vemos isso.
// interrompa o tópico em execução chamando o método de interrupção do thread public boolean cancel (boolean mayinterruptifrunning) {if (! (State == new && unsefe.comparandswapint (este, estateffset, novo, pode interferir? tente {// Caso Chame para interromper a exceção de lança se (MayInterruptifrunning) {try {thread t = runner; if (t! = null) t.Interrup (); } finalmente {// Estado final insefe.putOrderEdInt (isto, StateOffset, interrompido); }}} finalmente {finalizCompletion (); } retornar true; }Todos os problemas aqui são resolvidos.
Vamos resumir
Sempre existem soluções difíceis em projetos. Quando o Google não é fácil de encontrar, pode ser uma boa maneira de procurar o código -fonte do JDK.