springBoot定时器 你应该这样写

1 公司的结算模块业务线概括:需要一个定时任务去监测符合结算条件的数据,然后进行各个用户的分账。

这里使用到了springBoot 集成的定时器 Spring Task  ,为了数据安全,也更高效,使用到了多线程执行。

首先创建一个初始化线程的类

(图1)

@Configuration
public class ScheduleConfig implements SchedulingConfigurer, AsyncConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        TaskScheduler taskScheduler = taskScheduler();
        scheduledTaskRegistrar.setTaskScheduler(taskScheduler);
    }

    /**
     * 初始化线程池
     * @return
     */
    @Bean(destroyMethod = "shutdown")//通知关闭线程池
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(5);
        // 设置线程名前缀
        scheduler.setThreadNamePrefix("task-");
        // 等待所有线程执行完
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        return scheduler;
    }

    /**
     * 异步任务
     * @return
     */
    @Override
    public Executor getAsyncExecutor() {
        Executor executor = taskScheduler();
        return executor;
    }

    /**
     * 异常处理
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }

初始化5个线程来处理业务。

这里我们可以简单的看一下源码,为什么要初始化线程的数量 

因为(图1)实现了SchedulingConfigurer 这个类,(图2) SchedulingConfigurer 类并没有对线程数量进行约束,所以我们为了提高业务处理量,我们手动创建线程数量来处理数据。我们只需图1 重写 SchedulingConfigurer 里的 configureTasks 方法,就可以完成创建线程数量。

(图2)


package org.springframework.scheduling.annotation;

import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@FunctionalInterface
public interface SchedulingConfigurer {
    void configureTasks(ScheduledTaskRegistrar var1);
}

创建一个 DynamicScheduledTask 类 实现 SchedulingConfigurer  我们就可以重写线程类了。

@Configuration
@EnableScheduling
public class DynamicScheduledTask implements SchedulingConfigurer {

    // 定时器执行频率,半小时一次  0 0/30 * * * ?
    private static final String DEFAULT_CRON = "0 0/5 * * * ?";//五分钟执行一次
    private String cron = DEFAULT_CRON;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {

        scheduledTaskRegistrar.addTriggerTask(new Runnable() {
            @Override
            public void run() {
                doBiz();
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                // 定时任务触发,可修改定时任务的执行周期
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExecDate = trigger.nextExecutionTime(triggerContext);
                return nextExecDate;
            }
        });

    }

    /**
     * 定时器执行方法
     */
    public void doBiz() {

    }

    public String getCron() {
        return cron;
    }

    public void setCron(String cron) {
        this.cron = cron;
    }

}

好奇的童鞋可以点进去看一下源码,大概理解其思想,是有帮助的。

下面我们开始编写业务类,就是处理结算数据的代码模块

package com.example.fuxing.taskConfig;



public class test {


    /**
     * 扫描子订单表下订单状态值为4的数据,进行结算分账
     */

    @Component
    @Service
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public class ScanOrderTask extends DynamicScheduledTask {
        @Resource
        TimerService timerService;

        private Logger log = LoggerFactory.getLogger(this.getClass());

        public void doBiz() {
            try {
                DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                log.info("定时器开始执行" + sdf.format(new Date()) + "秒");
                List<FxOrderMedia> fxOrderMedia = timerService.runTimer();
                if (null != fxOrderMedia && fxOrderMedia.size() != 0) {

                    //执行代理商及平台分成
                    selectFxOrderMedia("");

                }
            } catch (Exception e) {
                throw new ResponseJsonException(FXErrorCode.Error, e.getMessage());
            }
        }

        /**
         * 查询订单的信息
         *
         * @param mediaOrdercode
         * @return
         */
        FxOrderMedia selectFxOrderMedia(String mediaOrdercode) {
            //查询订单的信息
            FxOrderMedia fxOrderMedia = timerService.selectFxOrderMedia(mediaOrdercode);
            JSONObject json = JSONObject.fromObject(fxOrderMedia);
            log.info("------所要结算的订单信息-------" + json.toString());
            //判断此订单是否为代理商下的订单
            if (!StringUtils.isEmpty(fxOrderMedia.getAgentcode()) && fxOrderMedia.getCommissionRatio() != new BigDecimal(0)) {
                //代理商分成
                Map<String, Object> returnDate = agencyShare(fxOrderMedia);
                if ("false".equals(returnDate.get("return").toString())) {
                    throw new ResponseJsonException(FXErrorCode.Error, "代理商分成失败!");
                }
            }
            //如果不是代理商用户
            Map<String, Object> map = platformDivision(fxOrderMedia);
            if ("false".equals(map.get("return").toString())) {
                throw new ResponseJsonException(FXErrorCode.Error, "平台分成失败!");
            }

            return fxOrderMedia;
        }

        /**
         * 代理商分成业务
         */
        private Map<String, Object> agencyShare(FxOrderMedia fxOrderMedia) {
            //分账A
            return null;
        }

        /**
         * 平台分成业务
         */
        private Map<String, Object> platformDivision(FxOrderMedia fxOrderMedia) {
            //分账B
            return null;
        }
    }

}

如有不对,请其指出,希望我们在前进的道路上互帮互助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值