编程知识 cdmana.com

Springboot utilise asynchrone le principe @ async et la configuration du pool de threads

Préface

Dans le développement de projets réels, de nombreux scénarios d'affaires doivent être réalisés de façon asynchrone,Comme un avis de message,Logging,Et tout ce qui est très commun peut être fait asynchrone,Amélioration de l'efficacité,Alors, dansSpringComment utiliser l'asynchrone dans le cadre

Utiliser les étapes

Il y a généralement deux façons de terminer une opération asynchrone,File d'attente des messagesMQ,EtTraitement du pool de threadsThreadPoolExecutor

EtSpring4Les paires fournies dansThreadPoolExecutorPool de Threads encapsulésThreadPoolTaskExecutor,Activer directement avec les annotations@Async,Cette note nous permet d'utiliserSpringIl est très pratique de faire des opérations asynchrones

Configurer la configuration des paramètres de la classe threadpool

Classe constante personnalisée

public class ConstantFiledUtil {
    public static final String AUTHORIZATION_TOKEN = "authorizationToken";
    /** * kmallNom du pool de threads */
    public static final String KMALL_THREAD_POOL = "KmallThreadPool";

    /** * kmallPréfixe du nom du fil */
    public static final String KMALL_THREAD_NAME_PREFIX = "kmall-thread-";
}

Copier le Code

Configurer le pool de Threads

@Configuration(proxyBeanMethods = false)
@EnableAsync //Ouvrir l'annotation
public class KmallConfig {
  
  @Bean(ConstantFiledUtil.KMALL_THREAD_POOL)
    public ThreadPoolTaskExecutor FebsShiroThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         //Configurer le nombre de fils de base
        executor.setCorePoolSize(5);
        //Configurer le nombre maximum de Threads
        executor.setMaxPoolSize(20);
        //Configurer la taille de la file d'attente
        executor.setQueueCapacity(200);
        //Temps libre autorisé pour les Threads de maintenance de pool de Threads
        executor.setKeepAliveSeconds(30);
        //Configurer le préfixe de nom du thread dans le pool de Threads
        executor.setThreadNamePrefix(ConstantFiledUtil.KMALL_THREAD_NAME_PREFIX);
        //Attendez que toutes les tâches soient terminées avant de continuer à détruire les autresBean
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //Définir le temps d'attente des tâches dans le pool de Threads,Si la destruction n'a pas eu lieu au - delà de ce délai,Pour s'assurer que l'application peut enfin être fermée,Au lieu de bloquer
        executor.setAwaitTerminationSeconds(60);
          // rejection-policy:QuandpoolAtteintmax sizeQuand,Comment gérer une nouvelle tâche
        // CALLER_RUNS:Ne pas exécuter la tâche dans le nouveau thread,Il est plutôt exécuté par le thread de l'appelant
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //Effectuer l'initialisation
        executor.initialize();
        return executor;
    }
   
}
Copier le Code

Notez qu'il faut passer ici@EnableAsyncActiver asynchrone sinon invalide

Tâches de filetage personnalisées

public interface ILogService extends IService<Log> {

    /** * Recherche de pages recherche d'informations sur le journal de requête * @param logParams * @return */
    IPage getSearchLogByPage(SearchLogParams logParams);

    /** * Enregistrer le journal * * @param logSubject */
    @Async
    void saveLog(LogSubject logSubject);
}
Copier le Code

Lorsque l'exécution asynchrone est nécessaireInterface,OuMéthodesAjouter@AsyncNote cette méthode est asynchrone,Appelé dans le programme principal,C'est une façon asynchrone d'exécuter un seul thread

Cette note indique quesaveLogLa méthode entre dans le pool de Threads qui estKmallThreadPoolCréé par la méthode.

Nous pouvons également spécifier le nom de la méthode séparément@Async("saveLogs")

De cette façon, lors de la journalisation, un seul thread exécute chaqueDemandeTout a répondu rapidement,Et les opérations longues sont laissées aux Threads dans le pool de Threads pour l'exécution asynchrone

Résumé

SpringUtilisation moyenne@AsyncComment annoter le marquage,Appelée méthode asynchrone.Inspring bootUtilisé dans l'application@AsyncC'est simple.:

  1. Appeler une classe de méthode asynchrone ou démarrer une classe avec des annotations@EnableAsync
  2. En plus de la méthode qui doit être appelée asynchrone@Async
  3. Utilisé@AsyncL'objet de classe de la méthode d'annotation doit êtreSpringGestion des conteneursbeanObjet;

Notez que l'invocation d'une méthode asynchrone dans la même classe n'est pas valide:Raison l'appel de méthode dans la classe par défaut ne sera pasaopInterception,C'est - à - dire que l'appelant et l'appelant sont dans la même classe,Il n'y a pas de tangente,L'objet n'a pas étéSpringGestion des conteneurs.C'est - à - dire:@AsyncMéthode non valable

Solutions:

Si vous voulez que les appels entre les méthodes de la même classe soient également interceptés,À utiliserspringObjet d'instance dans le conteneur,Au lieu d'utiliser par défautthis,Parce que passerbeanL'appel de l'instance seraspringDeaopInterception Comment utiliser cet exemple:AsyncService asyncService = context.getBean(AsyncService.class); Ensuite, utilisez cette référence pour appeler la méthode locale pour atteindre l'objectif d'interception Remarques:Cette méthode ne peut intercepter queprotected,default,publicMéthodes,privateLa méthode n'a pas pu intercepter.C'est...spring aopUn mécanisme.

Analyse des principes

Il ne peut y avoir que deux types de retour de méthode asynchrone:

  1. Lorsque le type de retour estvoidQuand,Les exceptions générées par la procédure d'appel de méthode ne sont pas lancées au niveau de l'appelant,Vous pouvez le faire en notantAsyncUncaughtExceptionHandlerPour capturer ce genre d'exception

  2. Lorsque le type de retour estFutureQuand,L'exception générée par la procédure d'appel de méthode est lancée au niveau de l'appelant

Notez que si vous ne Personnalisez pas les pools de Threads pour les méthodes asynchrones, ils sont utilisés par défautSimpleAsyncTaskExecutor.SimpleAsyncTaskExecutor:Pas un vrai pool de Threads,Cette classe ne réutilise pas les fils,Chaque appel crée un nouveau thread.Quand la concurrence est grandeProblèmes de performance graves.

SpringInterface de pool de thread asynchrone TaskExecutor

Voir le code source

@FunctionalInterface
public interface TaskExecutor extends Executor {
    void execute(Runnable var1);
}
Copier le Code

Il y a beaucoup de ses vraies classes primitives comme suit:

  1. SimpleAsyncTaskExecutor:Pas un vrai pool de Threads,Cette classe ne réutilise pas les fils,Chaque appel crée un nouveau thread.

  2. SyncTaskExecutor:Cette classe n'implémente pas d'appels asynchrones,Juste une opération de synchronisation.Uniquement pour les endroits où le Multithreading n'est pas nécessaire

  3. ConcurrentTaskExecutor:ExecutorClasse d'adaptateur pour,Non recommandé.SiThreadPoolTaskExecutorSi les exigences ne sont pas respectées,Pour envisager d'utiliser cette classe

  4. SimpleThreadPoolTaskExecutor:- Oui.QuartzDeSimpleThreadPoolLa classe de.Le pool de Threads est égalementquartzEt nonquartzUtiliser,Pour utiliser ce type de

  5. ThreadPoolTaskExecutor :Le plus souvent utilisé,Recommandations. C'est essentiellement vraijava.util.concurrent.ThreadPoolExecutorEmballage,

————————————————

Références aux articles

  1. Spring Boot(5) @AsyncDétails du pool de fils asynchrones
  2. segmentfault.com/a/119000004…

版权声明
本文为[Kenx]所创,转载请带上原文链接,感谢
https://cdmana.com/2021/09/20210914164725465l.html

Scroll to Top