最近在做的一个SpringBoot项目用到了定时任务管理,就用ThreadPoolTaskScheduler做动态添加修改删除定时任务,但在业务操作时线程池里取不到Bean对象,一直报空指针异常,最后发现注入的方式不对,通过下面这种方式注入是取不到Bean对象的。

    @Autowired
    private AccountAPIService accountAPIService;

    @Bean
    public AccountAPIService generalAPIService(APIConfiguration config) {
        return new AccountAPIServiceImpl(config);
    }

   

通过下面这种方式注入就可以取到Bean对象了:把对象定义为静态的,然后在set方法里注入

    private static AccountAPIService accountAPIService;
    
    @Resource(name = "accountAPIService")
    public static void setAccountAPIService(@Qualifier("config") APIConfiguration config) {
        TradeController.accountAPIService = new AccountAPIServiceImpl(config);
    }

ThreadPoolTaskScheduler:线程池任务调度类,能够开启线程池进行任务调度。下面是实际业务调用代码

import com.auto.trade.entities.SpringCorn;
import com.auto.trade.market.constant.COMMON_API_WRAPPER_STATIC_VALUE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ScheduledFuture;

/**
 * 任务调度线程池配置
 * @author QC班长
 * @date 20190127
 */
@Configuration
public class ScheduleConfig {

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

    //ThreadPoolTaskScheduler对象建议用下面这中方式注入,通过bean注解注册-代码更新于20191207
    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler(){
        return new ThreadPoolTaskScheduler();
    }

    private static ThreadPoolTaskScheduler threadPoolTaskScheduler;

    @Resource
    public  void setThreadPoolTaskScheduler(ThreadPoolTaskScheduler threadPoolTaskScheduler) {
        ScheduleConfig.threadPoolTaskScheduler = threadPoolTaskScheduler;
    }

    /**
     * 存放所有启动定时任务对象,极其重要
     */
    private static HashMap<String, ScheduledFuture<?>> scheduleMap = new HashMap<>();


    /**
     * @param crons 动态设置定时任务方法
     *              <p>
     *              此方法是真正的动态实现启停和时间周期的关键,你可以针对自己的业务来调用,你对库中的动态数据修改后来调用此方法,每个Cron对象必须要包含,执行周期(cron.getCron()),启停状态(cron.getCronStatus()),执行的类(cron.getCronClass())
     */
    public void startCron(List<SpringCorn> crons) {
        try {
            if (crons != null && !crons.isEmpty()) {
                //遍历所有库中动态数据,根据库中class取出所属的定时任务对象进行关闭,每次都会把之前所有的定时任务都关闭,根据新的状态重新启用一次,达到最新配置
                for (SpringCorn cron : crons) {
                    ScheduledFuture<?> scheduledFuture = scheduleMap.get(cron.getClass_name());
                    //一定判空否则出现空指针异常,ToolUtil为自己写的工具类此处只需要判断对象是否为空即可
                    if ((scheduledFuture != null)) {
                        scheduledFuture.cancel(true);
                    }
                }
                //因为下边存储的是新的定时任务对象,以前的定时任务对象已经都停用了,所以旧的数据没用清除掉,这步可以不处理,因为可以是不可重复要被覆盖
                //scheduleMap.clear();
                //遍历库中数据,之前已经把之前所有的定时任务都停用了,现在判断库中如果是启用的重新启用并读取新的数据,把开启的数据对象保存到定时任务对象中以便下次停用
                for (SpringCorn cron : crons) {
                    //判断当前定时任务是否有效,COMMON_API_WRAPPER_STATIC_VALUE.CORN_STATUS_TRUE为有效标识
                    if (cron.getStatus().equals(COMMON_API_WRAPPER_STATIC_VALUE.CORN_STATUS_TRUE)) {
                        //开启一个新的任务,库中存储的是全类名(包名加类名)通过反射成java类,读取新的时间
                        ScheduledFuture<?> future = threadPoolTaskScheduler.schedule((Runnable) Class.forName(cron.getClass_name()).newInstance(), new CronTrigger(cron.getCron()));
                        //这一步非常重要,之前直接停用,只停用掉了最后启动的定时任务,前边启用的都没办法停止,所以把每次的对象存到map中可以根据key停用自己想要停用的
                        scheduleMap.put(cron.getClass_name(), future);
                        logger.info("=================================>>>>> {} 定时业务每 {} 秒执行一次====================================", cron.getCron_remark(),cron.getCron());
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

GitHub 加速计划 / th / ThreadPool
7.74 K
2.22 K
下载
A simple C++11 Thread Pool implementation
最近提交(Master分支:2 个月前 )
9a42ec13 - 9 年前
fcc91415 - 9 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐