ITPub博客

首页 > 数据库 > 数据库开发技术 > SpringBoot 引入线程池+Queue缓冲队列实现高并发下单业务

SpringBoot 引入线程池+Queue缓冲队列实现高并发下单业务

原创 数据库开发技术 作者:后端Q 时间:2024-10-12 00:00:00 0 删除 编辑

在高并发下单业务场景中,有效地管理线程和队列能显著提高系统的吞吐量和响应能力。本文将介绍如何在SpringBoot项目中引入线程池和Queue缓冲队列,以实现高并发下单业务。我们将通过一个具体的例子来演示这一过程。

一、项目背景

假设我们有一个中小型项目,其中包含支付下单业务(仅办理VIP,不涉及商品库存)。虽然目前用户量还未上来,系统尚未出现问题,但考虑到未来用户量增大,下单并发量也会相应增加,我们决定提前进行高并发测试和优化。

二、可能遇到的问题

在高并发下单业务中,可能会遇到以下问题:

  1. 订单重复:由于高并发请求,可能会出现同一订单被重复处理的情况。
  2. 性能下降:当并发量增大时,如果处理不当,系统的性能可能会显著下降。

三、解决方式

为了解决上述问题,我们决定使用ThreadPoolExecutor线程池和Queue缓冲队列来管理并发请求。

四、实现步骤

1. 创建线程池配置类

首先,我们需要在SpringBoot项目中创建一个线程池配置类,用于配置线程池的参数。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class TaskPoolConfig {

    @Bean("taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); // 核心线程数
        executor.setMaxPoolSize(50); // 最大线程数
        executor.setQueueCapacity(100); // 队列容量
        executor.setThreadNamePrefix("taskExecutor-"); // 线程名前缀
        executor.setKeepAliveSeconds(60); // 线程空闲时间
        executor.setWaitForTasksToCompleteOnShutdown(true); // 等待所有任务完成后再关闭线程池
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝处理策略
        executor.initialize();
        return executor;
    }
}
2. 创建业务处理类

接下来,我们创建一个业务处理类,用于处理订单插入系统的逻辑。

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

@Component
@Scope("prototype")
public class BusinessThread implements Runnable {

    private String orderId;

    public BusinessThread(String orderId) {
        this.orderId = orderId;
    }

    @Override
    public void run() {
        // 业务操作
        System.out.println("多线程已经处理订单插入系统,订单号:" + orderId);
        // 模拟耗时操作
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
3. 创建线程池管理类

然后,我们创建一个线程池管理类,用于管理线程池和Queue缓冲队列。

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Queue;
import java.util.concurrent.*;

@Component
public class OrderThreadPoolManager implements BeanFactoryAware {

    private BeanFactory factory;

    private final static int CORE_POOL_SIZE = 10;
    private final static int MAX_POOL_SIZE = 50;
    private final static int WORK_QUEUE_SIZE = 100;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        factory = beanFactory;
    }

    private Map<String, Object> cacheMap = new ConcurrentHashMap<>();
    private Queue<Object> msgQueue = new LinkedBlockingQueue<>(WORK_QUEUE_SIZE);

    final RejectedExecutionHandler handler = new RejectedExecutionHandler() {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            msgQueue.offer(((BusinessThread) r).getOrderId());
            System.out.println("系统任务太忙了,把此订单交给(调度线程池)逐一处理,订单号:" + ((BusinessThread) r).getOrderId());
        }
    };

    final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAX_POOL_SIZE, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(WORK_QUEUE_SIZE), this.handler);

    public void addOrders(String orderId) {
        System.out.println("此订单准备添加到线程池,订单号:" + orderId);
        if (cacheMap.get(orderId) == null) {
            cacheMap.put(orderId, new Object());
            BusinessThread businessThread = new BusinessThread(orderId);
            threadPool.execute(businessThread);
        }
    }
}
4. 调用线程池管理类

最后,我们在需要的地方调用线程池管理类来处理订单。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private OrderThreadPoolManager orderThreadPoolManager;

    @PostMapping("/create")
    public String createOrder(String orderId) {
        orderThreadPoolManager.addOrders(orderId);
        return "订单处理中...";
    }
}

五、总结

通过上述步骤,我们成功在SpringBoot项目中引入了线程池和Queue缓冲队列,以实现高并发下单业务。这种方式能够有效地应对高并发场景,通过控制线程的数量和使用队列作为缓冲,避免了过度创建线程导致的资源消耗和性能下降。


原文作者:后端Q;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2023-01-22

  • 博文量
    1540
  • 访问量
    726709