需求描述:
点击查看文章后,进入文章详情页面,阅读数需要+1,如果在数据库表中添加一个字段更新+1,
存在问题:
(1)更新操作会在数据库表中加写锁,很影响性能;在多人访问时候,会导致文章无法查看的问题;
(2)而且如果将查看文章和阅读数+1作为一整套事务的话,当查询完文章详情后执行阅读数+1的操作时如果出现了问题,会导致整个流程中断,无法正常查看文章;
解决方法:
使用线程池技术
,将更新阅读数这一操作放到线程池中执行,不会影响主线程的查看文章详情的工作
具体实现:
- 编写线程池配置类ThreadPoolConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync//开启线程池
public class ThreadPoolConfig {
@Bean("taskExecutor")
public Executor asyncServiceExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(20);
//配置队列大小
executor.setQueueCapacity(Integer.MAX_VALUE);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("MyBlogThread");
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
//执行初始化
executor.initialize();
return executor;
}
}
- 编写service层ThreadService
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.guoxin.blog.dao.mapper.ArticleMapper;
import com.guoxin.blog.dao.pojo.Article;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class ThreadService {
// 在线程池中执行操作,不会影响主线程
@Async("taskExecutor")
public void updateArticleViewCount(ArticleMapper articleMapper, Article article) {
int viewCounts = article.getViewCounts();
Article articleUpdate = new Article();
articleUpdate.setViewCounts(viewCounts + 1);
LambdaUpdateWrapper<Article> updateWrapper = new LambdaUpdateWrapper();
updateWrapper.eq(Article::getId,article.getId());
// 为了在多线程环境下的线程安全
//update article set view_count=100 where view_count=99 and id=11;
updateWrapper.eq(Article::getViewCounts,viewCounts);
articleMapper.update(articleUpdate,updateWrapper);
}
}