4 способа для Spring Boot реализовать задачи синхронизации

Spring Boot
4 способа для Spring Boot реализовать задачи синхронизации

Существует несколько способов реализации задач на время:

Таймер: это класс java.util.Timer, который поставляется с java, этот класс позволяет вам планировать задачу java.util.TimerTask. Использование этого метода позволяет вашей программе выполняться с определенной частотой, но не в указанное время. Обычно используется меньше.

ScheduledExecutorService: это также класс, который поставляется с jdk; это класс задач по времени, разработанный на основе пула потоков.Каждая запланированная задача будет назначена потоку в пуле потоков для выполнения, то есть задачи выполняются одновременно и не влияют друг на друга.

Spring Task: Spring 3.0 поставляется с задачей, вы можете увидеть его как легкий кварц, а также использовать более простое, чем кварц.

Quartz: Это относительно мощный планировщик, позволяющий выполнять вашу программу в указанное время или с определенной частотой, что немного сложнее в настройке.

Использовать таймер

В настоящее время в проекте используется меньше, непосредственно вставьте демо-код. Подробное введение см. в API

public class TestTimer {

   public static void main(String[] args) {

       TimerTask timerTask = new TimerTask() {
           @Override
           public void run() {
               System.out.println("task  run:"+ new Date());
           }

       };

       Timer timer = new Timer();

       //安排指定的任务在指定的时间开始进行重复的固定延迟执行。这里是每3秒执行一次
       timer.schedule(timerTask,10,3000);
   }

}

Использование ScheduledExecutorService

Этот метод похож на Timer, просто посмотрите прямо на демо:

public class TestScheduledExecutorService {

   public static void main(String[] args) {

       ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

       // 参数:1、任务体 2、首次执行的延时时间
       //      3、任务执行间隔 4、间隔时间单位
       service.scheduleAtFixedRate(()->System.out.println("task ScheduledExecutorService "+new Date()), 0, 3, TimeUnit.SECONDS);

   }

}

Использование весенних задач

Простая запланированная задача

В проекте SpringBoot мы можем очень элегантно использовать аннотации для выполнения задачи синхронизации, сначала создайте проект, импортируйте зависимость:

<dependencies>

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
 </dependency>

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
 </dependency>

 <dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <optional>true</optional>
 </dependency>

 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
 </dependency>

</dependencies>

Создайте класс задач:

@Slf4j

@Component

public class ScheduledService {

   @Scheduled(cron = "0/5 * * * * *")
   public void scheduled(){
       log.info("=====>>>>>使用cron  {}",System.currentTimeMillis());
   }

   @Scheduled(fixedRate = 5000)
   public void scheduled1() {
       log.info("=====>>>>>使用fixedRate{}", System.currentTimeMillis());
   }

   @Scheduled(fixedDelay = 5000)
   public void scheduled2() {
       log.info("=====>>>>>fixedDelay{}",System.currentTimeMillis());
   }

}

Используйте аннотацию @EnableScheduling в основном классе, чтобы включить поддержку запланированных задач, а затем запустите проект.

Рекомендуется: Весенняя программа быстрого старта. Видно, что все три задачи на время были выполнены, и они выполняются последовательно в одном потоке.Если есть только одна задача на время, это не будет проблемой.Когда количество задач на время увеличивается, если одна задача зависла , другие задачи реализовать не сможет.

многопоточное выполнение

В традиционных проектах Spring мы можем добавить конфигурацию задачи в файл конфигурации xml, тогда как в проектах SpringBoot мы обычно используем класс конфигурации config для добавления конфигурации, поэтому создайте новый класс AsyncConfig. Обратите внимание на официальную учетную запись Java Technology Stack WeChat и ответьте на ключевое слово: весна на заднем плане, вы можете получить больше технических галантерейных товаров серии Spring, организованных лидером стека.

@Configuration
@EnableAsync
public class AsyncConfig {

    /*
     *此处成员变量应该使用@Value从配置中读取
    */
   private int corePoolSize = 10;
   private int maxPoolSize = 200;
   private int queueCapacity = 10;

   @Bean
   public Executor taskExecutor() {
       ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
       executor.setCorePoolSize(corePoolSize);
       executor.setMaxPoolSize(maxPoolSize);
       executor.setQueueCapacity(queueCapacity);
       executor.initialize();
       return executor;
   }

}

@Configuration: указывает, что класс является классом конфигурации.

@EnableAsync: включить поддержку асинхронных событий.

Затем добавьте @Async в класс или метод запланированной задачи. Наконец перезагрузите проект, каждая задача находится в другом потоке.

Конфигурация времени выполнения

В приведенной выше запланированной задаче мы используем аннотацию @Scheduled для метода, чтобы установить время выполнения задачи, и используем три метода настройки атрибутов:

fixedRate: определить временную задачу, которая выполняется с определенной частотой.

fixedDelay: определяет отложенную задачу, которая выполняется с определенной частотой. Отличие от вышеизложенного состоит в том, что изменение атрибута может быть объединено с initialDelay для определения отложенного времени выполнения задачи.

cron: настроить время выполнения задачи через выражения

Подробное объяснение выражений cron

Выражение cron содержит как минимум 6 (а возможно и 7) элементов времени, разделенных пробелами. Чтобы:

Секунды (0~59)

минуты (0~59)

час (0~23)

день (0~31)

Месяц (0~11)

Неделя (1~7 1=ВС или ВС, ПН, ВТ, СР, ЧТ, ПТ, СБ)

Год (1970-2099)

где каждый элемент может быть значением (например, 6), непрерывным интервалом (9-12), интервалом (8-18/4) (/ означает каждые 4 часа), списком (1,3,5), подстановочным знаком . Поскольку два элемента «день месяца» и «день недели» являются взаимоисключающими, необходимо установить один из них.

Пример конфигурации:

Выполнять каждые 5 секунд: /5 * ?

Выполнить каждую 1 минуту: 0/1?

0 0 10, 14, 16? Каждый день, в 14:00, 16:00

0 0/30 9-17 Каждые полчаса в течение 9-5 рабочих часов

0 0 12 ? * WED означает каждую среду в 12:00

«0 0 12 ?» Запускается в 12 часов дня каждый день.

«0 15 10 ?» срабатывает каждый день в 10:15.

«0 15 10 ?» срабатывает каждый день в 10:15.

«0 15 10 ? *» срабатывает каждый день в 10:15.

«0 15 10 ? 2005» срабатывает в 10:15 каждый день в 2005 году.

«0 14 * ?» срабатывает каждую минуту с 14:00 до 14:59 каждый день.

«0 0/5 14 ?» срабатывает каждые 5 минут с 14:00 до 14:55 каждый день.

«0 0/5 14,18 ?» срабатывает каждые 5 минут с 14:00 до 14:55 и с 18:00 до 18:55 каждый день.

«0 0-5 14 ?» срабатывает каждую минуту с 14:00 до 14:05 каждый день.

«0 10,44 14 ? 3 СР» Запускается каждую среду марта в 14:10 и 14:44.

«0 15 10 ? *ПН-ПТ» Запускается в 10:15 с понедельника по пятницу.

«0 15 10 15 * ?» срабатывает в 10:15 15-го числа каждого месяца.

«0 15 10 L * ?» срабатывает в 10:15 в последний день каждого месяца.

«0 15 10 ? * 6L» срабатывает в 10:15 в последнюю пятницу каждого месяца.

«0 15 10 ? * 6L 2002-2005» Запускается в 10:15 в последнюю пятницу каждого месяца с 2002 по 2005 год.

«0 15 10 ? * 6#3» срабатывает в 10:15 в третью пятницу каждого месяца.

Некоторые подвыражения могут содержать диапазоны или списки.

Например: подкпринение (день (неделя)) может быть "пн-пт", "пн, ср, пт", "пн - ср, сидел" Персонаж «*» представляет все возможные значения Персонаж «/» используется для уточнения приращения значения

Например: "0/15" в подвыражении (минуты) означает, начиная с 0-й минуты, каждые 15 минут «3/20» в подвыражении (минуты) означает, начиная с 3-й минуты, каждые 20 минут (имеет то же значение, что и «3, 23, 43») Символ «?» используется только для подвыражений дня (месяца) и дня (недели), указывая на то, что значение не указано. Когда одному из двух подвыражений присваивается значение, во избежание конфликтов значение другого подвыражения должно быть установлено на "?"

Символ «L» используется только в подвыражениях дня (месяца) и дня (недели), это сокращение от слова «последний». Если перед буквой «L» есть конкретное содержание, оно имеет другое значение.

Например: "6L" означает 6-й последний день месяца. Примечание. При использовании параметра «L» не указывайте список или диапазон, так как это может вызвать проблемы. Символ W обозначает дни недели (пн-пт) и может использоваться только в поле дня. Используется для указания дня недели, ближайшего к указанному дню. Большинство бизнес-процессов основано на рабочей неделе, поэтому символ W может быть очень важным.

Например, 15W в поле дня означает «день недели, ближайший к 15-му числу месяца». C: означает «Календарь». Это означает дату, с которой связан план, или, если дата не связана, она эквивалентна всем датам в календаре.

Например, 5C в поле даты эквивалентно первому дню после 5-го числа в календаре. 1С эквивалентно первому дню после воскресенья в поле дня недели.

Интегрированный кварц

добавить зависимости

Если версия SpringBoot более поздняя, ​​чем 2.0.0, а зависимость quart уже включена в spring-boot-starter, вы можете напрямую использовать зависимость spring-boot-starter-quartz:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

Если это 1.5.9, используйте следующее для добавления зависимостей:

<dependency>
  <groupId>org.quartz-scheduler</groupId>
  <artifactId>quartz</artifactId>
  <version>2.3.0</version>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
</dependency>

Здесь я использую SpringBoot версии 2.0.0.BUILD-SNAPSHOT, в эту версию начали интегрировать Quartz, так что очень удобно реализовать. Другие кажутся более хлопотными, поэтому я не буду их здесь представлять, я узнаю больше о Quartz, когда у меня будет время в будущем.

Создайте класс задач TestQuartz, который в основном наследует QuartzJobBean.

public class TestQuartz extends QuartzJobBean {

    /**
     * 执行定时任务
     * @param jobExecutionContext
     * @throws JobExecutionException
     */

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        System.out.println("quartz task "+new Date());

    }

}

Создайте класс конфигурации QuartzConfig

@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail teatQuartzDetail(){

        return JobBuilder.newJob(TestQuartz.class).withIdentity("testQuartz").storeDurably().build();

    }

    @Bean
    public Trigger testQuartzTrigger(){

        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(10)  //设置时间周期单位秒
                .repeatForever();
        return TriggerBuilder.newTrigger().forJob(teatQuartzDetail())

                .withIdentity("testQuartz")
                .withSchedule(scheduleBuilder)
                .build();

    }

}

Стартовый проект

Выше приведено краткое введение в обработку задач синхронизации SpringBoot, наиболее удобным должно быть использование аннотации SpringTask напрямую, а с версии 2.0 стало очень удобно использовать Quartz. Для этих двух методов следует сказать, что у каждого есть свои преимущества, поэтому выбирайте в соответствии со своими потребностями. Кроме того, подробности о Quartz можно найти в официальной документации.

Примечание: В тот момент, когда вам захочется сдаться, подумайте, почему вы вообще здесь оказались.