牛客网项目---6.5.任务执行和调度

初始任务执行和调度

我们需要定时计算各帖子的分数,清除临时文件等,这就需要任务调度的组件。

JDK线程池

  • ExecutorService:普通的线程池
  • ScheduledExecutorService:可以执行定时任务(分布式环境可能出问题)

Spring 线程池 

  • ThreadPoolTaskExecutor:普通的线程池
  • ThreadPoolTaskScheduler:可以执行定时任务(分布式环境可能出问题)

分布式定时任务 

  • Spring Quartz(将数据存储到数据库,分布式时可以共享数据) 
  1. 核心调度接口Scheduler
  2. 定义任务的接口Job的execute方法
  3. Jobdetail接口来配置Job的名字、组等
  4. Trigger接口配置Job的什么时候运行、运行频率
  5. QuartzConfig:配置 -> 数据库 -> 调用
  • FactoryBean可简化Bean的实例化过程 
  1. 通过FactoryBean封装Bean的实例化过程
  2. 将FactoryBean装配到Spring容器里
  3. 将FactoryBean注入给其他的Bean.
  4.  该Bean得到的是FactoryBean所管理的对象实例

如果我们采用JDK或者Spring的Scheduler执行定时任务在分布式环境可能出问题。因为JDK或者Spring的Scheduler设置的执行参数是保存在内存中,服务器之间不共享内存,当多个Scheduler操作时,就会产生问题。如果通过Quartz,就可以解决。Quartz的配置参数是保存在数据库中。
 

1.配置文件

#TaskExecutionProperties
  task:
    execution:
      pool:
        core-size: 5
        max-size: 15
        queue-capacity: 100

#TaskSchedulingProperties
    scheduling:
      pool:
        size: 5

2.配置类ThreadPoolConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@Configuration
@EnableScheduling
@EnableAsync
public class ThreadPoolConfig {
}

3.测试

3.1 AlphaService

    //让该方法在多线程环境下,被异步的调用
    @Async
    public void execute1(){
        logger.debug("execute1");
    }

    @Scheduled(initialDelay = 10000,fixedRate = 1000)
    public void execute2(){
        logger.debug("execute2");
    }

3.2 ThreadPoolTests

import com.nowcoder.community.service.AlphaService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Date;
import java.util.concurrent.*;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class ThreadPoolTests {

    private static final Logger logger= LoggerFactory.getLogger(ThreadPoolTests.class);

    // 1.JDK普通线程池
    private ExecutorService executorService= Executors.newFixedThreadPool(5);

    // 2.JDK可执行定时任务的线程池
    private ScheduledExecutorService scheduledExecutorService= Executors.newScheduledThreadPool(5);

    // 3.Spring普通线程池
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    // 4.Spring可执行定时任务的线程池
    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;

    @Autowired
    private AlphaService alphaService;

    private void sleep(long m){
        try {
            Thread.sleep(m);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 1.JDK普通线程池
    @Test
    public void testExecutorService(){

        for (int i = 0; i < 10; i++) {
            executorService.execute(()->{logger.debug("Hello ExecutorService");});
        }

        sleep(10000);
    }

    // 2.JDK定时任务线程池
    @Test
    public void testScheduledExecutorService(){
        scheduledExecutorService.scheduleAtFixedRate(()->{logger.debug("Hello ScheduledExecutorService");},
                10000,1000, TimeUnit.MILLISECONDS);

        sleep(30000);
    }

    // 3.Spring普通线程池
    @Test
    public void testThreadPoolTaskExecutor(){
        for (int i = 0; i < 10; i++) {
            taskExecutor.execute(()->{logger.debug("Hello ThreadPoolTaskExecutor");});
        }

        sleep(10000);
    }

    // 4.Spring定时任务线程池
    @Test
    public void testThreadPoolTaskScheduler(){
        Date startTime=new Date(System.currentTimeMillis()+10000);

        taskScheduler.scheduleAtFixedRate(()->{logger.debug("Hello ThreadPoolTaskScheduler");},startTime,1000);

        sleep(30000);
    }

    // 5.Spring普通线程池(简化)
    @Test
    public void testThreadPoolTaskExecutorSimple(){
        for (int i = 0; i < 10; i++) {
            alphaService.execute1();
        }

        sleep(10000);
    }

    // 6.Spring定时任务线程池(简化)
    @Test
    public void testThreadPoolTaskSchedulerSimple() {
        sleep(30000);
    }
}

4.Quartz

因为Quartz是基于数据库的,首先初始化tables_mysql_innodb.sql

  • qrtz_job_detail:对任务(job)描述的表
  • qrtz_simple_triggers:触发器有关的简单配置
  • qrtz_triggers:触发器有关的配置
  • qrtz_scheduler_state:定时器的有关内容
  • qrtz_locks:锁的信息

Quartz的基本组成部分:

  • 调度器:Scheduler:核心调度接口
  • 任务:时间Job接口,声明任务。通过JobDetail配置Job的详细参数
  • 触发器:Trigger,包括SimpleTrigger和CronTrigger,配置Job运行时的参数

 4.1 导入依赖

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

4.2 实现Job接口 AlphaJob

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

//例子
public class AlphaJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println(Thread.currentThread().getName() + "quartzJob");
    }
}

4.3 配置类QuartzConfig

import com.nowcoder.community.quartz.AlphaJob;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SimpleTriggerFactoryBean;

@Configuration
public class QuartzConfig {

    //FactoryBean作用:简化bean的实例化过程
    //1.通过FactoryBean封装Bean的实例化过程
    //2.将FactoryBean装配到spring容器中
    //3.将FactoryBean注入给其他的bean
    //4.其他的bean即可获得FactoryBean所管理的对象实例

    //1.配置jobDetail
    @Bean
    public JobDetailFactoryBean alphaJobDetail(){
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(AlphaJob.class);    //声明要配置的job类
        factoryBean.setName("alphaJob");           //声明job的名称
        factoryBean.setGroup("alphaJobGroup");    //声明job的分组
        factoryBean.setDurability(true);         //job是否长久的存在
        factoryBean.setRequestsRecovery(true);  //job是否可被恢复

        return factoryBean;
    }

    //2.配置trigger
    //  SimpleTriggerFactoryBean:简单的定时
    //  CronTriggerFactoryBean:可实现复杂的定时,如每年的1号进行清除
    @Bean
    public SimpleTriggerFactoryBean alphaTrigger(JobDetail alphaJobDetail){
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(alphaJobDetail);         //确定JobDetail
        factoryBean.setName("alphaTrigger");             //Trigger的名称
        factoryBean.setGroup("alphaTriggerGroup");      //Trigger的分组
        factoryBean.setRepeatInterval(3000);           //时间间隔3秒
        factoryBean.setJobDataMap(new JobDataMap());  //保存数据的类型

        return factoryBean;
    }
}

4.4 配置文件

# QuartzProperties
  quartz:
    job-store-type: jdbc                       #存储方式
    scheduler-name: communityScheduler         #调度器名称
    properties: {
                  org.quartz.scheduler.instanceId: AUTO,  #自动生成调度器的id
                  org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX, #存储需要的类
                  org.quartz.jobStore.driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate, #驱动
                  org.quartz.jobStore.isClustered: true,   #采用集群的方式
                  org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPool,  #所用线程池
                  org.quartz.threadPool.threadCount: 5    #线程池的数量
    }

4.5 删除Quartz数据库中job  QuartzTests

import org.junit.Test;
import org.junit.runner.RunWith;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class QuartzTest {

    //删除Quartz数据库中的job
    @Autowired
    private Scheduler scheduler;

    @Test
    public void deleteJob(){
        // JobKey(job的名称,job的组名)
        try {
            boolean b=scheduler.deleteJob(new JobKey("alphaJob","alphaJobGroup"));
            System.out.println(b);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值