【SpringBoot】异步执行,设置某些异步任务优先执行

异步线程设置优先级

前提: @Async 注解可以实现异步功能,但是如果想让其中一些异步任务先于一些异步任务执行,那么这个注解就实现不了了。

参考大神文章:这篇文章,需要大显神通

解决思路:为ThreadPoolTaskExecutor使用PriorityBlockingQueue

配置

@Bean("CustomTaskExecutor")
    public TaskExecutor threadPoolTaskExecutor(
            @Value("${spring.async.core-pool-size}") int corePoolSize,
            @Value("${spring.async.max-pool-size}") int maxPoolSize,
            @Value("${spring.async.queue-capacity}") int queueCapacity) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
            @Override
            protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
                return new PriorityBlockingQueue<>(queueCapacity);
            }
        };
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
      	//....你需要的其他配置
        return executor;
    }

这里的配置基本和使用@Async注解时配置线程池的无异,就是使用了PriorityBlockingQueue去为在等待队列中的线程设置优先级。

优先级比较

public class FutureCustomTask
        extends FutureTask<FutureCustomTask> implements Comparable<FutureCustomTask> {

    private JobTask task;

    public FutureCustomTask(JobTask task) {
        //这里null是因为执行任务不需要任何结果
        super(task, null);
        this.task = task;
    }

    @Override
    public int compareTo(FutureCustomTask o) {
        return task.getJob().getPriority().compareTo(o.task.getJob().getPriority());
    }
}

调试和输出结果

String类型任务优先级高,List类型任务优先级低

//先来两个String任务,占满核心线程池   核心线程池大小为2!!!
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doString,
              new JobEntity(stringParam, 1L))));
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doString,
              new JobEntity(stringParam, 1L))));
//再来任务试试看是否为优先级高的先执行
//这里先放 List 优先级低的任务,如果优先级配置生效,它应该最后执行。
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doList,
              new JobEntity(lpParam, 2L))));
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doString,
              new JobEntity(stringParam, 1L))));
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doString,
              new JobEntity(stringParam, 1L))));
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doString,
              new JobEntity(stringParam, 1L))));
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doString,
              new JobEntity(stringParam, 1L))));
taskExecutor.execute(new FutureCustomTask(
  new JobTask(jobBusiness::doString,
              new JobEntity(stringParam, 1L))));

输出结果:可见List任务在最后执行完成

2022-06-14 15:30:41.597  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:30:41.598  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:30:46.605  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : String 类型任务结束执行。
2022-06-14 15:30:46.605  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务结束执行。
2022-06-14 15:30:46.608  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:30:46.608  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:30:51.614  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : String 类型任务结束执行。
2022-06-14 15:30:51.616  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:30:51.614  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务结束执行。
2022-06-14 15:30:51.616  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:30:56.621  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务结束执行。
2022-06-14 15:30:56.621  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : String 类型任务结束执行。
2022-06-14 15:30:56.625  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:30:56.625  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : List 类型任务开始执行,休眠5秒模拟该条任务执行耗时------2022-06-14 15:31:01.631  INFO 19590 --- [mTaskExecutor-1] c.k.priority.businessTest.JobBusiness    : String 类型任务结束执行。
2022-06-14 15:31:01.631  INFO 19590 --- [mTaskExecutor-2] c.k.priority.businessTest.JobBusiness    : List 类型任务结束执行。

完整类

调试用的Controller

@RestController
public class PriorityController {

    @Autowired
    private TaskExecutor taskExecutor;
    @Autowired
    private JobBusiness jobBusiness;

    @GetMapping("/test")
    public String test() {
        String stringParam = "String任务----->";
        List<Map<String, String>> lpParam = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("1", "张三");
        map.put("2", "李四");
        lpParam.add(map);

        //先来两个String任务,占满核心线程池
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doString,
                        new JobEntity(stringParam, 1L))));
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doString,
                        new JobEntity(stringParam, 1L))));
        //再来任务试试看是否为优先级高的先执行
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doList,
                        new JobEntity(lpParam, 2L))));
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doString,
                        new JobEntity(stringParam, 1L))));
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doString,
                        new JobEntity(stringParam, 1L))));
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doString,
                        new JobEntity(stringParam, 1L))));
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doString,
                        new JobEntity(stringParam, 1L))));
        taskExecutor.execute(new FutureCustomTask(
                new JobTask(jobBusiness::doString,
                        new JobEntity(stringParam, 1L))));
        return "即时返回,任务正在异步执行。。。。。。";
    }
}

配置类

@Configuration
public class TaskConfiguration {

    @Bean("CustomTaskExecutor")
    public TaskExecutor threadPoolTaskExecutor(
            @Value("${spring.async.core-pool-size}") int corePoolSize,
            @Value("${spring.async.max-pool-size}") int maxPoolSize,
            @Value("${spring.async.queue-capacity}") int queueCapacity) {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
            @Override
            protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
                return new PriorityBlockingQueue<>(queueCapacity);
            }
        };
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        //....你需要的其他配置
        return executor;
    }
}

任务类

public class FutureCustomTask
        extends FutureTask<FutureCustomTask> implements Comparable<FutureCustomTask> {

    private JobTask task;

    public FutureCustomTask(JobTask task) {
        //这里null是因为执行任务不需要任何结果
        super(task, null);
        this.task = task;
    }

    @Override
    public int compareTo(FutureCustomTask o) {
        return task.getJob().getPriority().compareTo(o.task.getJob().getPriority());
    }
}
public class JobEntity<T> {
    private T jobInfo;
    private Long priority;

    public JobEntity(T jobInfo, Long priority) {
        this.jobInfo = jobInfo;
        this.priority = priority;
    }

    public T getJobInfo() {
        return jobInfo;
    }

    public void setJobInfo(T jobInfo) {
        this.jobInfo = jobInfo;
    }

    public Long getPriority() {
        return priority;
    }

    public void setPriority(Long priority) {
        this.priority = priority;
    }
}
public class JobTask implements Runnable {

    private Consumer<JobEntity> jobConsumer;

    private JobEntity jobEntity;

    public JobTask(Consumer<JobEntity> jobConsumer, JobEntity jobEntity) {
        this.jobConsumer = jobConsumer;
        this.jobEntity = jobEntity;
    }

    public JobEntity getJob() {
        return this.jobEntity;
    }

    @Override
    public void run() {
        this.jobConsumer.accept(jobEntity);
    }
}

业务方法类

@Component
public class JobBusiness {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * String 类型任务
     *
     * @param: jobEntity
     * @return: void
     */
    public void doString(JobEntity<String> jobEntity) {
        logger.info("String 类型任务开始执行,休眠5秒模拟该条任务执行耗时------》");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("String 类型任务结束执行。");
    }

    /**
     * 接受List类型任务
     *
     * @param: jobEntity
     * @return: void
     */
    public void doList(JobEntity<List<Map<String, String>>> jobEntity) {
        logger.info("List 类型任务开始执行,休眠5秒模拟该条任务执行耗时------》");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        logger.info("List 类型任务结束执行。");
    }
}

application.properties

spring.async.core-pool-size=2
spring.async.queue-capacity=3
spring.async.max-pool-size=5
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值