前言
每年"双十一"这场全球最大的购物狂欢节中,电商平台需要在极短时间内向海量用户精准发放数亿张优惠券,除了系统硬件本身的性能需要提升之外,程序的代码也是十分重要的。本文将深入解密某电商平台双十一优惠券批量下发的核心技术架构,重点解析如何通过线程池与Java 8 Consumer接口构建高并发处理系统,实现秒级完成百万级优惠券发放的技术突破,同时也通用工具类实现其他场景批量发送。
程序结构概述
本文实践实践基于springboot实现,所以优惠券批量下发系统主要由以下几个核心部分组成:
- 控制器(Controller):负责接收外部请求并触发批量任务。
- 服务接口(CouponServiceV2):定义了批量任务处理的接口方法。
- 服务实现类(CouponServiceImplV2):实现了批量任务处理逻辑,利用线程池并发执行任务。
- 批量发送工具类(TaskBatchSendUtils):提供了通用的批量任务处理方法,支持自定义任务处理逻辑。
控制器层
首先控制器层是系统与外部交互的入口,负责接收请求并调用相应的服务方法。在本系统中,控制器通过一个简单的HTTP GET请求触发优惠券的批量下发任务。
typescript
@GetMapping(value = "/coupon/sendv2")
public void sendv2() {
couponServiceV2.batchTaskActionV2();
}
述代码中,当访问/coupon/sendv2
接口时,控制器会调用couponServiceV2
的batchTaskActionV2
方法,从而启动批量优惠券下发流程。
服务接口层
这里也就是Service层,Service层定义了系统所需的核心功能,便于后续的实现和扩展。在本系统中,定义了一个CouponServiceV2
接口,其中包含一个batchTaskActionV2
方法,用于执行批量任务。
csharp
public interface CouponServiceV2 {
public void batchTaskActionV2();
}
服务实现类
接下来就是,Service层实现类,主要是负责具体的业务逻辑实现。在本系统中,CouponServiceImplV2
类实现了CouponServiceV2
接口,并在batchTaskActionV2
方法中完成了优惠券的批量下发任务, 模拟要下发的50条优惠卷,上游系统给我们的下发优惠卷源头,并且调用工具类批处理任务,这些优惠卷coupons,放入线程池threadPool,做什么业务disposeTask下发。
csharp
@Override
public void batchTaskActionV2() {
//1 模拟要下发的50条优惠卷,上游系统给我们的下发优惠卷源头
List<String> coupons = getCoupons();
long startTime = System.currentTimeMillis();
//2 调用工具类批处理任务,这些优惠卷coupons,放入线程池threadPool,做什么业务disposeTask下发
TaskBatchSendUtils.send(coupons, threadPool, TaskBatchSendUtils::disposeTaskV2);
long endTime = System.currentTimeMillis();
System.out.println("----costTime: "+(endTime - startTime) +" 毫秒");
}
批量发送工具类
接下来就是定义批量发送工具类TaskBatchSendUtils, TaskBatchSendUtils
工具类封装了批量任务处理的核心逻辑,利用Java的并发工具类CountDownLatch
确保所有任务都完成后再继续后续操作。同时,通过Java 8的Consumer
接口,支持灵活的任务处理逻辑,TaskBatchSendUtils无需关心具体业务逻辑,只要对Consumer进行accept即可,这样后续也可以通过改工具类实现其他场景批量发送。
核心方法:send
typescript
public class TaskBatchSendUtils {
public static <T> void send(List<T> taskList, Executor threadPool, Consumer<? super T> consumer) throws InterruptedException {
if (taskList == null || taskList.size() == 0) {
return;
}
if(Objects.isNull(consumer)) {
return;
}
CountDownLatch countDownLatch = new CountDownLatch(taskList.size());
for (T couponOrShortMsg : taskList) {
threadPool.execute(() -> {
try {
consumer.accept(couponOrShortMsg);
} finally {
countDownLatch.countDown();
}
});
}
countDownLatch.await();
}
// 具体的任务处理方法
public static void disposeTask(String task) {
System.out.println(String.format("【%s】disposeTask下发优惠卷或短信成功", task));
}
public static void disposeTaskV2(String task) {
System.out.println(String.format("【%s】disposeTask下发邮件成功", task));
}
public static void disposeTaskV3(String task) {
System.out.println(String.format("【%s】disposeTask下发二维码序号成功", task));
}
}
线程池配置
批量发送的关键,主要是利用线程池,合理的线程池配置可以显著提升系统的并发处理能力和稳定性,以下是线程池配置:
scss
@Configuration
public class ThreadPoolConfig
{
//线程池配置
@Resource
private ThreadPoolProperties threadPoolProperties;
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
// 核心线程池大小
threadPool.setCorePoolSize(threadPoolProperties.getCorePoolSize());
// 最大可创建的线程数
threadPool.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
// 等待队列最大长度
threadPool.setQueueCapacity(threadPoolProperties.getQueueCapacity());
// 线程池维护线程所允许的空闲时间
threadPool.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
//异步方法内部线程名称
threadPool.setThreadNamePrefix("spring默认线程池-");
// 线程池对拒绝任务(无线程可用)的处理策略
threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 任务都完成再关闭线程池
threadPool.setWaitForTasksToCompleteOnShutdown(true);
// 任务初始化
threadPool.initialize();
return threadPool;
}
}
通过合理配置线程池,可以有效地管理并发任务,防止资源耗尽和系统崩溃。
Java 8的Consumer接口
这里简单介绍一下Java 8引入的Consumer
接口,它是是一个函数式接口,表示接受一个输入参数并且不返回结果的操作。在本系统中,Consumer
接口被用于定义任务的处理逻辑,使得任务处理逻辑可以灵活地传入和替换。
csharp
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
在本文中,通过方法引用(如TaskBatchSendUtils::disposeTaskV2
)将具体的任务处理逻辑传递给TaskBatchSendUtils.send
方法,实现了任务处理逻辑的解耦和复用。
测试验证
通过上述设计和实现,系统能够高效地处理批量优惠券下发任务,利用线程池并发执行任务,显著提升了任务处理速度和系统吞吐量,接下来启动程序,查看最后耗时情况:

结语
本文详细介绍了一个基于线程池和Java 8的Consumer
接口实现的优惠券批量下发系统。通过合理的架构设计和并发处理,系统能够高效地处理大量任务,提升系统性能和用户体验。在实际应用中,开发者可以根据具体业务需求,进一步优化和扩展系统功能,以满足更复杂的业务场景,欢迎大家到评论区进行留言。