基于线程池和CompletableFuture实现抽奖系统10连抽

一:配置文件

java 复制代码
# 线程池配置
thread:
  pool:
    executor:
      config:
        core-pool-size: 20
        max-pool-size: 50
        keep-alive-time: 5000
        block-queue-size: 5000
        policy: CallerRunsPolicy

二 config:

java 复制代码
@Data
@ConfigurationProperties(prefix = "thread.pool.executor.config", ignoreInvalidFields = true)
public class ThreadPoolConfigProperties {

    /** 核心线程数 */
    private Integer corePoolSize = 20;
    /** 最大线程数 */
    private Integer maxPoolSize = 200;
    /** 最大等待时间 */
    private Long keepAliveTime = 10L;
    /** 最大队列数 */
    private Integer blockQueueSize = 5000;
    /*
     * AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
     * DiscardPolicy:直接丢弃任务,但是不会抛出异常
     * DiscardOldestPolicy:将最早进入队列的任务删除,之后再尝试加入队列的任务被拒绝
     * CallerRunsPolicy:如果任务添加线程池失败,那么主线程自己执行该任务
     * */
    private String policy = "AbortPolicy";

}
java 复制代码
@Slf4j
@EnableAsync
@Configuration
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
public class ThreadPoolConfig {

    @Bean
    @ConditionalOnMissingBean(ThreadPoolExecutor.class)
    public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties properties) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 实例化策略
        RejectedExecutionHandler handler;
        switch (properties.getPolicy()){
            case "AbortPolicy":
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
            case "DiscardPolicy":
                handler = new ThreadPoolExecutor.DiscardPolicy();
                break;
            case "DiscardOldestPolicy":
                handler = new ThreadPoolExecutor.DiscardOldestPolicy();
                break;
            case "CallerRunsPolicy":
                handler = new ThreadPoolExecutor.CallerRunsPolicy();
                break;
            default:
                handler = new ThreadPoolExecutor.AbortPolicy();
                break;
        }
        // 创建线程池
        return new ThreadPoolExecutor(properties.getCorePoolSize(),
                properties.getMaxPoolSize(),
                properties.getKeepAliveTime(),
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(properties.getBlockQueueSize()),
                Executors.defaultThreadFactory(),
                handler);
    }

}

三: 定义抽奖逻辑

java 复制代码
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class LotterySystem {

    // 模拟抽奖逻辑,返回一个随机奖品
    public static String drawLottery() {
        // 模拟抽奖过程,假设奖品列表
        List<String> prizes = List.of("一等奖", "二等奖", "三等奖", "谢谢参与");
        int index = ThreadLocalRandom.current().nextInt(prizes.size());
        return prizes.get(index);
    }
}

四: 逻辑

java 复制代码
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

public class LotterySystemWithCompletableFuture {

	@Resource
    private ThreadPoolExecutor executorService ;

    public static void main(String[] args) {
    

         // 创建10个异步抽奖任务
        List<CompletableFuture<String>> futures = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                // 打印当前线程信息
                System.out.println("Current thread: " + Thread.currentThread().getName());
                return LotterySystem.drawLottery();
            }, executorService);
            futures.add(future);
        }

        // 使用allOf等待所有抽奖完成,并收集结果
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
        CompletableFuture<List<String>> resultsFuture = allFutures.thenApply(v -> 
            futures.stream()
                   .map(CompletableFuture::join)
                   .collect(Collectors.toList())
        );

        // 获取最终结果并打印
        List<String> results = resultsFuture.join();
        results.forEach(System.out::println);

        // 关闭线程池
        executorService.shutdown();
    }
}
相关推荐
传奇开心果编程21 分钟前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
SL_staff23 分钟前
财务系统慎用低代码?从数据模型闭环看合规落地的技术实践
java·低代码·全栈
滕州市燕猫虎计算机科技工作室个体工商户31 分钟前
IDEA:Command line is too long
java·ide·intellij-idea
步行cgn1 小时前
Spring p 命名空间注入详解
java·前端·spring
YatHinLay1 小时前
MyBatis 流式查询实战:ResultHandler 处理海量数据
java
天天被压力1 小时前
【跨市场数据实战 #08】可转债折价机会怎么筛:3个接口抓比价、列表和实时盘口
java·人工智能·python
张某布响丸辣2 小时前
附件下载的安全边界:路径白名单、NAS 哨兵文件与 Redis Lua 一次性令牌
java·redis·redis lua·nas哨兵
YatHinLay3 小时前
Spring Boot + Calcite 实现跨库查询
java
酷炫码神3 小时前
MosMos 创意效果与能力边界展示
java
Wang's Blog3 小时前
Java 接入Redis: 使用Jedis操作Redis
java·服务器·redis