1、只要是批处理任务(比如下发几万张优惠券,发京豆),就必定用到线程池、不丢包
2、业务场景:下发五万张优惠券,要求一张都不能少。
3、BatchTaskManager
@Service
public class BatchTaskManager {
private static final int _1W = 10000;
@Resource
private ThreadPoolTaskExecutor threadPool;
public void batchTaskAction() {
// 查询业务数据,模拟从数据库查询出1W条记录
List<String> taskList = simulationQueryDB();
try {
// 调用工具类批处理任务,这些优惠卷taskList,放入线程池treadPool,做什么业务disposeTask下发
TaskDisposeUtils.send(taskList, threadPool, TaskDisposeUtils::disposeTask);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
private List<String> simulationQueryDB() {
List<String> data = new ArrayList<>();
// 模拟查询数据库
for (int i = 1; i <= 5 * _1W; i++) {
data.add(String.valueOf(i));
}
return data;
}
}
4、TaskDisposeUtils
public class TaskDisposeUtils {
public static <T> void send(List<T> taskList, Executor threadPool, Consumer<? super T> consumer) throws InterruptedException {
if (CollUtil.isEmpty(taskList)) {
return;
}
if (Objects.isNull(consumer)) {
return;
}
CountDownLatch countDownLatch = new CountDownLatch(taskList.size());
for (T item : taskList) {
threadPool.execute(() -> {
try {
consumer.accept(item);
} finally {
countDownLatch.countDown();
}
});
}
countDownLatch.await();
}
public static void disposeTask(String task) {
System.out.println(String.format("【%s发送成功】", task));
}
}
5、BatchTaskController
@RestController
public class BatchTaskController {
@Resource
private BatchTaskManager batchTaskManager;
// GET http://localhost:8089/batchTask
@GetMapping("/batchTask")
public String batchTask() {
batchTaskManager.batchTaskAction();
return "本次活动派发流水:" + IdUtil.simpleUUID() + "派发时间:" + DateUtil.now();
}
}