1.说明

*这都是我想的,可能不是都对,如有纰漏,还望指正
1)线程池,线程池根据配置,允许最大n个线程同时执行
2)序列,就像一个list一样,但是它里面放的是一个Thread对象,线程池会从序列中取任务线程,然后执行
3)此次需求是现有订单,需要调用三方接口查询状态,所有大致思路是:
	1).定时任务查出需要验证的订单
	2).加入到线程序列中
	3).如果序列中有需要执行的,线程池来处理

2.步骤

(0).创建一个配置类

在后面用得到,需要从中取注入spring的service等,替代@Resource

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class BeanContext implements ApplicationContextAware {

    // Spring应用上下文环境
    private static ApplicationContext applicationContext;

    /*
     * 实现了ApplicationContextAware 接口,必须实现该方法;
     * 通过传递applicationContext参数初始化成员变量applicationContext
     */
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanContext.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext(){
        return applicationContext;
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T)applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> clz) throws BeansException {
        return (T)applicationContext.getBean(clz);
    }
}

(1).创建线程池与序列

我创建在了一个新的配置类中,你也可以放在启动类里
先创建序列,然后创建线程,传入创建的序列与线程池关联,来看下创建线程池的几个关键参数

参数

解释

corePoolSize

核心线程池大小,我理解为最大并行线程数

maximumPoolSize

最大线程池大小

keepAliveTime

线程最大空闲时间

TimeUnit.SECONDS

时间(秒)这个我也没仔细查干什么用的

blockingQueue

对应序列

代码如下

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
public class ThreadPoolConfig {

    /**
     * 创建序列
     * @return queue
     */
    @Bean(name = "orderCheckQueue")
    public ArrayBlockingQueue<Runnable> orderCheckQueue(){
        ArrayBlockingQueue<Runnable> objects = new ArrayBlockingQueue<>(5000);
        log.info("订单验证序列初始化完成");
        return objects;
    }

    /**
     * 创建线程池
     * @param blockingQueue queue
     * @return pool
     */
    @Bean(name = "orderCheckThreadPool")
    public ThreadPoolExecutor orderCheckThreadPool(@Qualifier(value = "orderCheckQueue") ArrayBlockingQueue<Runnable> blockingQueue){
        int corePoolSize = 8;
        int maximumPoolSize = 32;
        long keepAliveTime = 60;
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, blockingQueue);
        threadPoolExecutor.prestartAllCoreThreads();
        log.info("订单验证线程池初始化完成");
        return threadPoolExecutor;
    }
    
}

(2)创建线程执行对象

线程执行对象里不能用@Resource @Autowired,需要使用构造方法注入,并从springContext中取service对象
XOrderInfoDao是一个mapper,演示注入方法
XOrderInfoEntity这个对象是我的订单类,这里传进来然后在run()方法中执行验证验证订单的步骤

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class OrderVerifyExecutors implements Runnable{

    XOrderInfoEntity order;

    /*使用构造方法注入service*/
    private final XOrderInfoDao orderInfoDao;

    /*构造方法中操作service*/
    public OrderVerifyExecutors(XOrderInfoEntity order){
        this.order =  order;
        this.orderInfoDao = BeanContext.getApplicationContext().getBean(XOrderInfoDao.class);
    }

    @Override
    public void run() {
	xxx
        //线程该执行的事情
    }
}

(3)其实到这里就已经OK了,线程池有了,序列有了,线程执行方法也配置了,只要药使用定时任务,将XOrderInfoEntity对象添加到序列就可以了,这里使用定时任务,如下

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;

@Slf4j
@Component
//@Profile("beta")//只在生产环境启动
public class DalOrderJob {

    //注入解析序列
    @Resource(name = "orderCheckQueue")
    private ArrayBlockingQueue<Runnable> orderCheckQueue;

    @Resource
    private XOrderInfoDao orderInfoDao;

    @Scheduled(cron = "1 0/5 * * * ?")
    public void methodRun() {
        //查出订单,循环创建OrderVerifyExecutors执行对象,并添加到序列
        List<XOrderInfoEntity> all = orderInfoDao.findAll();
        all.forEach(item -> {
            orderCheckQueue.add(new OrderVerifyExecutors(item));
        });
    }
}

需要注意的是,如果序列满了,就会添加不进去,会报错,需要添加前判断满没有,满了就sleep(),等会儿再加,我这里需要检查的订单量并不是很多,先不加了

如需转载,请附上原文地址如过你有问题,或者文章有问题,欢迎探讨指正