24.01.17

异步

使用

    @Resource
    ThreadPoolTaskExecutor taskExecutor;
taskExecutor.execute(()->{
//业务代码
        });

开启异步注解

@Configuration
@MapperScan("com.javasm.mingming.*.dao")
@EnableAsync//开启异步任务注解
public class ServerConfig {
​
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

使用

在方法上面,加
只有跨类调用的时候生效
@Async

定时

启动

@Configuration
@MapperScan("com.javasm.mingming.*.dao")
@EnableAsync//开启异步任务注解
@EnableScheduling//启动定时任务
public class ServerConfig {
​
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

固定不可以改变的定时任务

在编码阶段,已经固定了定时的逻辑,不能在不停止服务器的情况下更改逻辑

配置信息可以不设置,原本自带的

spring:  
  task:
    execution:
      pool:
        core-size: 10
        max-size: 50
        queue-capacity: 1000
    scheduling:
      pool:
        size: 10
@Component
public class TestTask {
​
    Logger logger = LogManager.getLogger(TestTask.class);
​
    //我希望多久/什么频率, 执行一次/多次 当前的方法
    //每隔5秒执行1次
    //cron="秒 分 小时 日期 月份 星期 年"
    //星期和日期互斥,不能同时设置,必须有1个是?  年是可以省略的
    @Scheduled(cron = "0/5 * * * * ?")
    @Async//异步
    public void f1(){
        logger.info("---------------测试f1 ------每隔5秒执行1次");
    }
    //从第10秒开始,每秒执行1次,第20秒的时候终止
    @Scheduled(cron = "10-20 * * * * ?")
    @Async//可选,是否加异步,取决于自己
    public void f2(){
        logger.info("===========f2--从第10秒开始,每秒执行1次,第20秒的时候终止");
    }
}
#经典案例:
0 * * * * * ?  每分钟执行一次
“30 * * * * ?” 每分钟第30秒触发任务
“30 10 * * * ?” 每小时的10分30秒触发任务 
“30 10 1 * * ?” 每天1点10分30秒触发任务 
“30 10 1 20 * ?” 每月20号1点10分30秒触发任务 
“30 10 1 20 10 ? *” 每年10月20号1点10分30秒触发任务 
“30 10 1 20 10 ? 2011” 2011年10月20号1点10分30秒触发任务 
“30 10 1 ? 10 * 2011” 2011年10月每天1点10分30秒触发任务 
“30 10 1 ? 10 SUN 2011” 2011年10月每周日1点10分30秒触发任务 
“15,30,45 * * * * ?” 每分钟的第15秒,30秒,45秒时触发任务 
“15-45 * * * * ?” 15到45秒内,每秒都触发任务 
“15/5 * * * * ?” 每分钟的每15秒开始触发,每隔5秒触发一次 
“15-30/5 * * * * ?” 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次 
“0 0/3 * * * ?” 每小时的第0分0秒开始,每三分钟触发一次 
“0 15 10 ? * MON-FRI” 星期一到星期五的10点15分0秒触发任务 
“0 15 10 L * ?” 每个月最后一天的10点15分0秒触发任务 
“0 15 10 LW * ?” 每个月最后一个工作日的10点15分0秒触发任务 
“0 15 10 ? * 5L” 每个月最后一个星期四的10点15分0秒触发任务 
“0 15 10 ? * 5#3”每个月第三周的星期四的10点15分0秒触发任务
  • 同步新闻

    @Resource
    NewsService newsService;
​
    @Scheduled(cron = "0 0 0/1 * * ?")
    @Async
    public void f3(){
        logger.info("每天0:0:0开始同步新闻列表,每隔1个小时执行1次");
        newsService.syncNews();
    }

大部分场景是固定的定时任务

可变定时任务

新建数据库

CREATE TABLE `sys_task` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL COMMENT '任务名称',
  `clazz` varchar(255) DEFAULT NULL COMMENT '执行任务的类',
  `cron` varchar(255) DEFAULT NULL COMMENT '定时任务表达式',
  `status` int DEFAULT '0' COMMENT '状态0关闭1开启',
  `ctime` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

创建配置文件

@Component
public class JavasmSchedulerConfigurer implements SchedulingConfigurer {
​
    Logger logger = LogManager.getLogger(JavasmSchedulerConfigurer.class);
​
    private ScheduledTaskRegistrar scheduledTaskRegistrar;
​
    private Map map = new ConcurrentHashMap<>();
​
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        //项目启动的时候,就已经调用了这个方法,是在启动成功之前调用的
        //考虑到有可能有多个定时任务,所以,创建一个线程池,专门用来存放定时任务
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
        ConcurrentTaskScheduler taskScheduler = new ConcurrentTaskScheduler(executorService);
        //开启注册 定时任务对象
        scheduledTaskRegistrar.setScheduler(taskScheduler);
        //放到全局变量,这样其他方法,就可以调用/使用  参数了
        this.scheduledTaskRegistrar = scheduledTaskRegistrar;
    }
​
    @Resource
    ApplicationContext applicationContext;
    //创建并开始任务
    public boolean regTask(SysTask task){
        if (task == null){
            return false;
        }
        //任务id
        Integer id = task.getId();
        //执行任务的类
        String clazz = task.getClazz();
        //表达式
        String cron = task.getCron();
        //new对象
        try {
            Class aClass = Class.forName(clazz);
            //Object o = aClass.getConstructor().newInstance();
            Object bean = applicationContext.getBean(aClass);
          //Runnable接口是Java提供的一种用于实现多线程的接口,通过实现Runnable接口,可以将任务逻辑放入run()方法中,随后通过Thread类或其他执行器(如ExecutorService)来创建和启动线程,从而实现多线程并发执行
            //这里通过反射从数据获得包名路径
            
            Runnable runnable = (Runnable) bean;
            //执行任务对象
            CronTask cronTask = new CronTask(runnable, cron);
            //任务开始,
            ScheduledTask scheduledTask = this.scheduledTaskRegistrar.scheduleCronTask(cronTask);
            //把已经开始的任务对象,存入全局,等待停止
            map.put(id,scheduledTask);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return true;
    }
    
    public void stop(Integer id) {
        ScheduledTask scheduledTask = map.get(id);
        if (scheduledTask != null){
            //停止定时任务
            scheduledTask.cancel();
            map.remove(id);
        }
    }
}

被强行转换为Runnable的

@Component
public class NewTask implements Runnable{
​
    Logger logger = LogManager.getLogger(NewTask.class);
​
    @Resource
    NewsService newsService;
​
    @Override
    public void run() {
        logger.info("同步新闻列表");
        newsService.syncNews();
    }
}
@Service("sysTaskService")
public class SysTaskServiceImpl extends ServiceImpl implements SysTaskService {
​
    @Resource
    JavasmSchedulerConfigurer javasmSchedulerConfigurer;
    @Resource
    ThreadPoolTaskExecutor taskExecutor;
​
    @Override
    public void startTask(Integer id) {
        //查询 任务信息
        SysTask sysTask = getById(id);
        if (javasmSchedulerConfigurer.regTask(sysTask)){
            taskExecutor.execute(()->{
                //成功
                //修改任务状态
                sysTask.setStatus(1);
                updateById(sysTask);
            });
​
        }
    }
​
    @Override
    public void stopTask(Integer id) {
        javasmSchedulerConfigurer.stop(id);
        //主要业务的代码,不能放到多线程中
        //主要业务执行之后的次要业务,比如说修改状态,添加一些附表的值/修改缓存等,可以放入子线程,用来提高效率
        //线程池
        taskExecutor.execute(()->{
            SysTask sysTask = new SysTask();
            sysTask.setId(id);
            sysTask.setStatus(0);
            updateById(sysTask);
        });
​
    }
}

创建前端项目

image-20250117105558697

你可能感兴趣的:(java,数据库,前端)