前言
小说内容页作为小说精品屋-plus中的核心模块页面,承载着用户90%以上的访问量,下面将详细讲解小说内容页的设计和实现,以及如何通过多线程来提高小说内容页的性能和系统吞吐量。
优化效果
优化前(业务代码单线程串行执行):
优化后(业务代码多线程并行执行):
设计与实现
- application.yml配置文件中新建线程池配置。
#线程池配置 thread: pool: #核心线程池数量 core-pool-size: 10 #最大线程池数量 maximum-pool-size: 20 #线程超时时间(秒) keep-alive-time: 10 #队列大小 queue-size: 100
- 新建线程池配置属性类。
@Data @Component @ConfigurationProperties(prefix = "thread.pool") public class ThreadPoolProperties { private Integer corePoolSize; private Integer maximumPoolSize; private Long keepAliveTime; private Integer queueSize; }
- 新建线程池配置类。
@Configuration public class ThreadPoolConfig { @Bean public ThreadPoolExecutor threadPoolExecutor(ThreadPoolProperties properties) { return new ThreadPoolExecutor(properties.getCorePoolSize(), properties.getMaximumPoolSize(), properties.getKeepAliveTime(), TimeUnit.SECONDS, new LinkedBlockingDeque<>(properties.getQueueSize()), new ThreadPoolExecutor.AbortPolicy()); } }
- 业务代码实现。
//加载小说基本信息线程 CompletableFuture<Book> bookCompletableFuture = CompletableFuture .supplyAsync(() -> { //查询书籍 Book book = bookService.queryBookDetail(bookId); log.debug("加载小说基本信息线程结束"); return book; }, threadPoolExecutor); //加载小说章节信息线程 CompletableFuture<BookIndex> bookIndexCompletableFuture = CompletableFuture .supplyAsync(() -> { //查询目录 BookIndex bookIndex = bookService.queryBookIndex(bookIndexId); log.debug("加载小说章节信息线程结束"); return bookIndex; }, threadPoolExecutor); //加载小说上一章节信息线程,该线程在加载小说章节信息线程执行完毕后才执行 CompletableFuture<Long> preBookIndexIdCompletableFuture = bookIndexCompletableFuture .thenApplyAsync((bookIndex) -> { //查询上一章节目录ID Long preBookIndexId = bookService.queryPreBookIndexId(bookId, bookIndex.getIndexNum()); log.debug("加载小说上一章节信息线程结束"); return preBookIndexId; }, threadPoolExecutor); //加载小说下一章节信息线程,该线程在加载小说章节信息线程执行完毕后才执行 CompletableFuture<Long> nextBookIndexIdCompletableFuture = bookIndexCompletableFuture .thenApplyAsync((bookIndex) -> { //查询下一章目录ID Long nextBookIndexId = bookService.queryNextBookIndexId(bookId, bookIndex.getIndexNum()); log.debug("加载小说下一章节信息线程结束"); return nextBookIndexId; }, threadPoolExecutor); //加载小说内容信息线程 CompletableFuture<BookContent> bookContentCompletableFuture = CompletableFuture .supplyAsync(() -> { //查询内容 BookContent bookContent = bookService.queryBookContent(bookIndexId); log.debug("加载小说内容信息线程结束"); return bookContent; }, threadPoolExecutor); //判断用户是否需要购买线程,该线程在加载小说章节信息线程执行完毕后才执行 CompletableFuture<Boolean> needBuyCompletableFuture = bookIndexCompletableFuture .thenApplyAsync((bookIndex) -> { //判断该目录是否收费 if (bookIndex.getIsVip() != null && bookIndex.getIsVip() == 1) { //收费 UserDetails user = getUserDetails(request); if (user == null) { //未登录,需要购买 return true; } //判断用户是否购买过该目录 boolean isBuy = userService.queryIsBuyBookIndex(user.getId(), bookIndexId); if (!isBuy) { //没有购买过,需要购买 return true; } } log.debug("判断用户是否需要购买线程结束"); return false; }, threadPoolExecutor);
总结
通过小说精品屋-plus小说内容页的设计和实现,我们可以发现使用多线程优化的核心主要在于对线程池核心线程数、最大线程数、队列大小等参数的选择,这些配置参数应该根据实际环境来决定,我们可以通过压力测试工具如JMeter来辅助我们确定这些参数的最优值范围。