Maison  >  Article  >  Java  >  Comment implémenter le propre pool de threads de Springboot

Comment implémenter le propre pool de threads de Springboot

王林
王林avant
2023-06-28 16:33:05806parcourir

One : ThreadPoolTaskExecuto

1 ThreadPoolTaskExecutor Pool de threads :

ThreadPoolTaskExecutor est l'encapsulation secondaire de Spring basée sur le propre pool de threads de Java, ThreadPoolExecutor. L'objectif principal est de rendre plus pratique l'utilisation des pools de threads dans le système Spring Framework. Pool de threads Spring

2 Utilisez ThreadPoolTaskExecutor pour injecter des beans dans ioc
Formulaire de fichier de configuration, Spring configurera automatiquement

## 默认线程池配置,ThreadPoolTaskExecutor 
# 核心线程数
spring.task.execution.pool.core-size=8  
# 最大线程数
spring.task.execution.pool.max-size=16
# 空闲线程存活时间
spring.task.execution.pool.keep-alive=60s
# 是否允许核心线程超时
spring.task.execution.pool.allow-core-thread-timeout=true
# 线程队列数量
spring.task.execution.pool.queue-capacity=100
# 线程关闭等待
spring.task.execution.shutdown.await-termination=false
spring.task.execution.shutdown.await-termination-period=
# 线程名称前缀
spring.task.execution.thread-name-prefix=demo_Thread

Formulaire de configuration :

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledFuture;
//@Configuration
public class ThreadConfig {
    @Value("${task.maxPoolSize}")
    private int maxPoolSize;
    //todo 其他的相关配置都可以通过配置文件中注入
    @Bean("ThreadPoolTaskExecutor")
    public Executor myAsync() {
        final ThreadPoolTaskExecutor executor =
                new ThreadPoolTaskExecutor();
        executor.setMaxPoolSize(maxPoolSize);
        //todo  其他参数设置
        //初始化
        executor.initialize();
        return executor;
    }
}

3 Après la création des threads, tous les pools de threads sont obtenus à partir d'ioc

4 Processus de traitement du pool de threads :

(1) Vérifiez si le pool de threads principaux est plein. Sinon, créez un thread pour effectuer la tâche. Si le nombre de threads principaux est plein, vérifiez si la file d'attente des tâches est pleine. Sinon, stockez le thread dans. la file d'attente des tâches. Si la file d'attente des tâches est pleine, vérifiez le nombre maximum de threads. Si le nombre n'est pas satisfait, créez un thread pour exécuter la tâche. Si elle est pleine, exécutez-la conformément à la politique de rejet.

    CallerRunsPolicy() : exécution du thread d'origine
  • AbortPolicy() : lancer une exception directement
  • DiscardPolicy() : rejeter directement
  • DiscardOldestPolicy() : supprimer la tâche la plus ancienne de la file d'attente
  • 2: ThreadPoolTasksCheduler

1 ThreadpoolTasksCheduler planifie régulièrement les pools de threads de tâche pour traiter les tâches asynchrones

2 Utilisation: Inject ThreadpoolTaskscheduler Bean

(1) Format de fichier de configuration: ..

(2) Format de la classe de configuration:

rreea
3 Utilisez les tâches planifiées ThreadPoolTaskScheduler

pour utiliser le pool de threads ordinaire :

    soumettre (appelable), besoin d'exécuter le résultat
  • soumettre (exécutable), aucun résultat d'exécution n'est requis
  • (1) Tâche planifiée

Ajouter le contenu de la tâche Exécutable, définir le cycle d'exécution Déclencheur/Date, Expression de déclenchement Baidu peut

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledFuture;
@Configuration
public class ThreadPoolTaskSchedulerConfig {
    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        final ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        //设置等待任务在关机时l候完成
        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        //设置等待时间为60s
        threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
        return threadPoolTaskScheduler;
    }
}

(2) Spécifier l'intervalle Temps d'exécution d'une tâche, l'intervalle de temps va de l'achèvement de la tâche précédente au début de la tâche suivante , en millisecondes

 schedule(Runnable task,Trigger)
 schedule(Runnable task,Date)

(3) Exécutez des tâches à une fréquence fixe, exécutez de nouvelles tâches à intervalles réguliers après le début de la tâche, si la dernière tâche est terminée, puis attendez que la tâche suivante soit exécutée une fois la dernière exécution de la tâche terminée

 scheduleWithFixedDelay(Runnable task,long delay)

(4) Annulation de tâche planifiée :

Définissez la collection pour le stockage des tâches planifiées. Le résultat de l'exécution de la tâche planifiée est ScheduledFuture6b3d0130bba23ae47fe2b8e8cddf0195, et stockez l'objet dans la collection, annulez la tâche planifiée en obtenant le ScheduledFutured3d9b9f783327ed2591f7765666b0b22 object.cancel(true) dans la collection

 scheduleAtFixedRate(Runnable task,long delay)

Trois @Scheduled implémente la tâche planifiée, l'annotation active la tâche planifiée

1 Utilisez @EnableScheduled pour activer la prise en charge

2 @Méthode d'annotation planifiée

(1) @ Scheduled(fixedDelay=5000) exécution différée, exécutée après 5 secondes

(2) @Scheduled(fixedRate=5000) exécution planifiée, exécutée toutes les cinq secondes

(3) @Scheduled(corn="002* *?") Exécution personnalisée, maïs expression Baidu, cette méthode d'exécution est couramment utilisée, corn="002**?"Commencez à exécuter les tâches planifiées à deux heures du matin tous les jours

3 Notez que les tâches démarrées par @Scheduled sont monothread, facile à bloquer

(1) Injectez ThreadPoolTaskScheduler dans ioc, puis Scheduled utilisera le pool de threads ThreadPoolTaskScheduler, ce qui peut résoudre le problème de blocage d'un seul thread

(2) Les annotations @Scheduled et @Async activent les tâches planifiées, spécifiées dans @Async("pool" ) Pool de threads, s'il n'y a pas de pool de threads spécifié, le pool de threads SimpleAsyncTaskExecutor de Spring sera utilisé. Ce pool de threads ajoutera un thread pour exécuter la tâche à chaque fois, ce qui est inefficace 4 : Tâches asynchrones au Spring


1 @EnableAsync tourne. sur le support asynchrone

2 @Async active les tâches asynchrones et spécifie le pool de threads

Remarque : les annotations @Scheduled et @Async activent les tâches planifiées et spécifient le pool de threads dans @Async("pool"). Le pool de threads SimpleAsyncTaskExecutor de Spring sera utilisé.Ce pool de threads ajoutera un thread pour exécuter la tâche à chaque fois, ce qui est inefficace. Cependant, si @Async active la tâche asynchrone séparément, il est recommandé d'utiliser le pool de threads par défaut. pour personnaliser le pool de threads en fonction des besoins. Remarque : La valeur de retour de @Async ne peut être que void ou Future, l'appelant et @Async ne peuvent pas être dans la même classe, sinon aop ne sera pas utilisé

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
@Service
public class SchedulerService {
    @Autowired
    ThreadPoolTaskScheduler scheduler;
    /**
     * 常规线程池使用
     */
    public void tesScheduler1() throws ExecutionException, InterruptedException {
        //无返回值
        final Future<?> demo_scheduler1 = scheduler.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("demo runnable scheduler");
            }
        });
        //无返回值
        final Future<?> demo_scheduler2 = scheduler.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                System.out.println("demo callable  scheduler");
                return "callable";
            }
        });
        System.out.println("result:" + demo_scheduler2.get());
    }
    /**
     * 定时任务
     */
    public void tesScheduler2() throws ParseException {
        //CronTrigger表达式百度即可
        scheduler.schedule(() -> {
            System.out.println("定时任务");
        }, new CronTrigger("0/1****?"));
        //创建指定时间的日期
        final Date date = new Date(2023, 3, 26, 21, 35);
        final DateFormat format = new SimpleDateFormat();
        final Date parse = format.parse("2023-03-26-21-26");
        scheduler.schedule(() -> {
            System.out.println(new Date());
        }, parse);
    }
    /**
     * 指定时间间隔执行任务,上次任务结束到下次任务开始的时间间隔
     */
    public void tesScheduler3() {
        scheduler.scheduleWithFixedDelay(() -> {
            //todo
        }, 300L);
    }
    /**
     * 固定频率执行任务,在固定一段时间后便会执行下次任务,
     * 如果时间到了上次任务还没执行完毕则等待,
     * 直到上一次任务执行完毕后立马执行下次任务
     */
    public void tesScheduler4() {
        scheduler.scheduleAtFixedRate(new FutureTask<String>(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        return null;
                    }
                }),
                200);
    }
    //取消定时任务队列
    public static ConcurrentMap<String, ScheduledFuture> map = new ConcurrentHashMap<>();
    public void startTask(String k1) {
        map.compute(k1, (k, v) -> {
            if (map.containsKey(k)) return v;
            map.put(k, v);
            return v;
        });
    }
}

Five: Present ; un pool de threads Java personnalisé :

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
    @Async
    public void showThreadName1() {
        //默认线程池
        System.out.println(Thread.currentThread().getName());
    }
    @Async("myPool")//指定线程池
    public void showThreadName2() {
        System.out.println(Thread.currentThread().getName());
    }
}

le propre pool de threads de Java, cache, numéro fixe, monothread, chronométré,,,, six ou sept types, à suivre plus tard

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer