任务执行和调度----Spring线程池/Quartz

定时任务

在服务器中可能会有定时任务,但是不知道分布式系统下次会访问哪一个服务器,所以服务器中的任务就是相同的,这样会导致浪费。使用Quartz可以解决这个问题。
任务执行和调度----Spring线程池/Quartz_第1张图片

JDK线程池

@RunWith(SpringRunner.class)
@SpringBootTest	
@ContextConfiguration(classes = MyCommunityApplication.class)
public class ThreadPoolTest {

    private Logger logger = LoggerFactory.getLogger(ThreadPoolTest.class);

	// JDK's normal thread-pool
    private ExecutorService executorService = Executors.newFixedThreadPool(5);

    // JDK's thread pool that periodically executes tasks
    private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

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

    @Test
    public void testExecutorService() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.info("hello executor service");
            }
        };

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

        sleep(10000);
    }

    @Test
    public void testScheduleExecutorService(){
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.info("hello executor service");
            }
        };

		// 初始时间间隔为10000ms,任务间隔为1000ms
        for(int i = 0; i < 10; i++) {
            scheduledExecutorService.scheduleAtFixedRate(task, 10000, 1000, TimeUnit.MILLISECONDS);
        }

        sleep(30000);
    }
}

Spring线程池

配置application.properties

# Spring thread pool
# TaskExecutionProperties
spring.task.execution.pool.core-size=5
spring.task.execution.pool.max-size=15
spring.task.execution.pool.queue-capacity=100
# TaskScheduleProperties
spring.task.scheduling.pool.size=5

Spring线程池默认不开启定时线程池,需要新建配置类手动开启:

@Configuration
@EnableScheduling	// 允许定时线程池
@EnableAsync		// 允许多线程执行
public class ThreadPoolConfig {

}

基于注入

测试方法:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = MyCommunityApplication.class)
public class ThreadPoolTest {

    private Logger logger = LoggerFactory.getLogger(ThreadPoolTest.class);

    // Spring's normal thread pool
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    // Spring's thread pool that periodically executes tasks
    // 如果配置类不加@EnableScheduling会报错
    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;

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

    @Test
    public void testThreadPoolTaskExecutor(){
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.info("hello spring thread pool");
            }
        };

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

        sleep(10000);
    }

    @Test
    public void testThreadPoolTaskScheduler(){
        Runnable task = new Runnable() {
            @Override
            public void run() {
                logger.info("hello spring thread pool");
            }
        };

        Date start = new Date(System.currentTimeMillis() + 10000);
//        for(int i = 0; i < 10; i++){
            taskScheduler.scheduleAtFixedRate(task, start, 1000);
//        }

        sleep(10000);
    }
}

基于注解

@Service
public class AlphaService {
	
	// 此前已经在配置类上允许了异步及定时
	// @EnableScheduling	// 允许定时线程池
	// @EnableAsync		// 允许异步执行

	// 加上这个注解说明是异步的
    @Async
    public void execute1(){
        logger.info("hello");
    }

	// 加上这个注解说明是定时任务
	// 第一次延迟10s,之后每次间隔1s
	// @Scheduled默认为单线程,开启多个任务时,任务的执行时机会受上一个任务执行时间的影响。
    @Scheduled(initialDelay = 10000, fixedRate = 1000)
    public void execute2(){
        logger.info("hello2");
    }
}
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = MyCommunityApplication.class)
public class ThreadPoolTest {

    private Logger logger = LoggerFactory.getLogger(ThreadPoolTest.class);

    // Spring's normal thread pool
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    // Spring's thread pool that periodically executes tasks
    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;

    @Autowired
    private AlphaService alphaService;

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

    @Test
    public void testThreadPoolTaskExecutorSimple2(){
    	// 此处不需要调用alphaService.execute2方法
    	// 因为有Scheduled注解的方法在程序开始时会自动执行
//      alphaService.execute2();
        sleep(30000);
    }
}

分布式定时任务

新建任务

参考链接
任务执行和调度----Spring线程池/Quartz_第2张图片
引入依赖包

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

		dependency>

配置Quartz

# QuartzProperties
spring.quartz.job-store-type=jdbc
spring.quartz.scheduler-name=communityScheduler
spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO
#spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
spring.quartz.properties.org.quartz.jobStore.class=org.springframework.scheduling.quartz.LocalDataSourceJobStore
spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
spring.quartz.properties.org.quartz.jobStore.isClustered=true
spring.quartz.properties.org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
spring.quartz.properties.org.quartz.threadPool.threadCount=5

定义Job类:

public class AlphaJob implements Job {

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

定义Quartz的配置类,该配置类只执行一次便被存入数据库的几个表中任务执行和调度----Spring线程池/Quartz_第3张图片

// this configuration just for the first execution, and then the configuration will be saved in the database
@Configuration
public class QuartzConfig {

    // `FactoryBean` simplify the instantiation process of `Bean`
    // 1.The instantiation process of `Bean` is encapsulated through `FactoryBean`
    // 2.Assemble `FactoryBean` into `Spring`'s container
    // 3.Inject `FactoryBean` into the other beans
    // 4.This bean can acquire the object instance of the bean managed by the `FactoryBean`

    // inject `JobDetailFactoryBean` into this class
    // config `JobDetail`
    @Bean
    public JobDetailFactoryBean alphaJobDetail() {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(AlphaJob.class);
        factoryBean.setName("alphaJob");
        factoryBean.setGroup("alphaGroup");
        // this task will be stored permanently although there are no triggers existing
        factoryBean.setDurability(true);
        // this task can be recovered after meeting some faults
        factoryBean.setRequestsRecovery(true);

        return factoryBean;
    }

    // the `JobDetail` used is the object instance in `JobDetailFactoryBean`
    // config `Trigger(SimpleTriggerFactoryBean, CronTriggerFactoryBean)`
    @Bean
    public SimpleTriggerFactoryBean alphaTrigger(JobDetail alphaJobDetail) {
        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
        factoryBean.setJobDetail(alphaJobDetail);
        factoryBean.setName("alphaTrigger");
        factoryBean.setGroup("alphaGroup");
        // the interval of the trigger
        factoryBean.setRepeatInterval(3000);
        // use an object to store the status of the job, `JobDataMap()` is the default object
        factoryBean.setJobDataMap(new JobDataMap());

        return factoryBean;
    }
}

启动程序后,Job自动执行,可以看到任务相关的信息已经自动加入到了表中:

删除任务

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

    @Autowired
    private Scheduler scheduler;

    @Test
    public void testDeleteJob(){
        try {
            boolean result = scheduler.deleteJobs(Collections.singletonList(new JobKey("alphaJob", "alphaGroup")));
            System.out.println(result);
        } catch (SchedulerException e) {
            throw new RuntimeException(e);
        }
    }
}

可以看到,数据库中已经没有了关于任务的记录

你可能感兴趣的:(java杂文,spring,java,后端)