定时任务Quartz和线程池的使用示例

任务执行和调度

线程池

JDK线程池

1.JDK普通线程池:ExecutorService

	 // JDK普通线程池,工厂方法去创建
    private ExecutorService executorService = Executors.newFixedThreadPool(5);
    
    @Test
    public void testExecutorService() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.debug("Hello ExecutorService");
            }
        };

        for (int i = 0; i < 10; i++) {
            // submit提交会给一个线程去执行
            executorService.submit(task);
        }

        sleep(10000);
    }

2.JDK定时任务线程池 :scheduledExecutorService

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

    @Test
    public void testScheduledExecutorService() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.debug("Hello ScheduledExecutorService");
            }
        };

        // 定时任务执行;scheduleAtFixedRate以固定的频率去执行,执行多次
        // scheduleWithFixedDelay 推迟多久去执行,执行一次
        scheduledExecutorService.scheduleAtFixedRate(task, 10000, 1000, TimeUnit.MILLISECONDS);

        sleep(30000);
    }

Spring线程池

Spring线程池配置类

@Configuration
@EnableScheduling   // 启用定时任务的注解
@EnableAsync        // 让@Async注解有效
public class ThreadPoolConfig {
}

Spring普通线程池:ThreadPoolTaskExecutor

    // Spring普通线程池
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;
 
    @Test
    public void testThreadPoolTaskExecutor() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.debug("Hello ThreadPoolTaskExecutor");
            }
        };

        for (int i = 0; i < 10; i++) {
            taskExecutor.submit(task);
        }

        sleep(10000);
    }

Spring定时任务线程池 :ThreadPoolTaskScheduler

    // Spring可执行定时任务的线程池
    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;
    
    @Test
    public void testThreadPoolTaskScheduler() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.debug("Hello ThreadPoolTaskScheduler");
            }
        };

        Date startTime = new Date(System.currentTimeMillis() + 10000);
        taskScheduler.scheduleAtFixedRate(task, startTime, 1000);

        sleep(30000);
    }

Spring 普通线程池(简化)

	 @Test
    public void testThreadPoolTaskExecutorSimple() {
        for (int i = 0; i < 10; i++) {
            alphaService.execute1();
        }

        sleep(10000); //等待子线程结束,否则当前线程直接结束,子线程可能没有执行完
    }
	// @Async让该方法在多线程环境下,被异步的调用. 需要配置类上注解@EnableAsync
    @Async
    public void execute1() {
        logger.debug("execute1");
    }

Spring定时任务线程池(简化)

	@Test
    public void testThreadPoolTaskSchedulerSimple() {
        sleep(30000);
    }
	// 只要有任务执行,这个就会执行
    @Scheduled(initialDelay = 10000, fixedRate = 1000)
    public void execute2() {
        logger.debug("execute2");
    }

Quartz

# QuartzProperties
spring.quartz.job-store-type=jdbc
spring.quartz.scheduler-name=communityScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
# 任务存到数据库里用JobStoreTX类进行操作
spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
# 任务存到数据库里时用的jdbc驱动
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
# 采用集群的方式
spring.quartz.properties.org.quartz.jobStore.isClustered=true
# Quartz使用的线程池
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
spring.quartz.properties.org.quartz.threadPool.threadCount=5

配置之后会把任务写到数据库里,定时任务分布式部署不会出现问题

job接口里进行任务的定义,execute方法中写要做的事情

public class AlphaJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println(Thread.currentThread().getName() + ": execute a quartz job.");
    }
}

在配置类中,配置JobDetail和Trigger

// 第一次执行访问配置文件,把配置信息放到DB中,后续从DB中去调用
// 配置 -> 数据库 -> 调用
@Configuration
public class QuartzConfig {

    // FactoryBean可简化Bean的实例化过程:
    // 1.spring通过FactoryBean封装Bean的实例化过程.
    // 2.将FactoryBean装配到Spring容器里.
    // 3.将FactoryBean注入给其他的Bean.
    // 4.该Bean得到的是FactoryBean所管理的对象实例.

    // 配置JobDetail
     @Bean
    public JobDetailFactoryBean alphaJobDetail() {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(AlphaJob.class); // 声明管理的job的类
        factoryBean.setName("alphaJob");         // job的名字
        factoryBean.setGroup("alphaJobGroup");
        factoryBean.setDurability(true);       // 声明任务持久保存
        factoryBean.setRequestsRecovery(true); // 任务是可恢复的
        return factoryBean;
    }

    // 配置Trigger(SimpleTriggerFactoryBean, CronTriggerFactoryBean)
     @Bean
    public SimpleTriggerFactoryBean alphaTrigger(JobDetail alphaJobDetail) {
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(alphaJobDetail);   // 设置trigger对哪个job做的触发器,传的是jobdetail
        factoryBean.setName("alphaTrigger");
        factoryBean.setGroup("alphaTriggerGroup");
        factoryBean.setRepeatInterval(3000);        // 执行job的频率
        factoryBean.setJobDataMap(new JobDataMap());// 存job的状态
        return factoryBean;
    }

job存到DB中,项目启动以后就会自动定时执行

删除DB中的job

public class QuartzTests {

    @Autowired
    private Scheduler scheduler;

    // 删除DB中的job
    @Test
    public void testDeleteJob() {
        try {
            boolean result = scheduler.deleteJob(new JobKey("alphaJob", "alphaJobGroup"));
            System.out.println(result);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

}

版权声明:本文为L_zhenxiang原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。