1. 异步任务使用

  (1)创建线程池配置

@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("lewang");
        //等待所有线程执行完成后关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //执行初始化
        executor.initialize();
        return executor;
    }

}

  (2)在查看文章时对更新操作使用异步

    /*
        文章详情
     */
    @PostMapping("/view/{id}")
    public Result findArticleById(@PathVariable("id") Long articleId){
        return articleService.findArticleById(articleId);
    }

    @Override
    public Result findArticleById(Long articleId) {
        /**
         * 1. 根据id查询文章信息
         * 2. 根据body id和categoryid去做关联查询
         */
        Article article = articleMapper.selectById(articleId);
        ArticleVo articleVo = copy(article, true, true,true,true);

        //查看完文章,需要新增阅读数,需要执行更新操作,更新时会加写锁,阻塞其他读操作,性能低
        //更新操作增加了此次接口的耗时,如果有问题就影响查看操作
        //这是可以使用线程池,把更新操作放到线程池中执行和主线程就不相关了
        String view_count = (String) redisTemplate.opsForHash().get("view_count", String.valueOf(articleId));
        if(view_count != null){
            articleVo.setViewCounts(Integer.parseInt(view_count));
        }
        threadService.updateArticleViewCount(articleMapper,article);
        return Result.success(articleVo);
    }

@Component
public class ThreadService {

    //期望此操作在线程池中执行,不会影响原有的主线程
    @Async("taskExecutor")  //在线程池中执行此任务
    public void updateArticleViewCount(ArticleMapper articleMapper, Article article) {
        try {
            int viewCounts = article.getViewCounts();
            Article articleUpdate = new Article();
            articleUpdate.setViewCounts(viewCounts+1);
            LambdaUpdateWrapper<Article> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Article::getId,article.getId());
            //对id和viewCounts都进行判断,为了在多线程环境下,viewCounts不会被其他的线程已经修改过
            updateWrapper.eq(Article::getViewCounts,viewCounts);
            //update article set view_count = 100 where view_count=99 and id = 11
            articleMapper.update(articleUpdate,updateWrapper);
            Thread.sleep(5000);
            System.out.println("更新完成了...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

2. 定时任务

@Slf4j
@Component
// @EnableAsync
 @EnableScheduling
public class HelloScheduled {

     @Scheduled(cron = "* * * * * ?")
     public void hello() {
         log.info("hello...");
         try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }

     }
}
2023-09-24 17:29:36.001  INFO 9512 --- [   scheduling-1] c.l.g.seckill.scheduled.HelloScheduled   : hello...
2023-09-24 17:29:40.014  INFO 9512 --- [   scheduling-1] c.l.g.seckill.scheduled.HelloScheduled   : hello...
2023-09-24 17:29:44.005  INFO 9512 --- [   scheduling-1] c.l.g.seckill.scheduled.HelloScheduled   : hello...
2023-09-24 17:29:48.015  INFO 9512 --- [   scheduling-1] c.l.g.seckill.scheduled.HelloScheduled   : hello...

定时任务默认时阻塞的,可以通过定时任务和异步结合的方式来解决定时任务阻塞的问题

@Slf4j
@Component
 @EnableAsync
 @EnableScheduling
public class HelloScheduled {
    /**
     *   定时任务不该阻塞。默认是阻塞的
     *      1)、可以让业务以异步的方式,自己提交到线程池
     *              CompletableFuture.runAsync(() -> {
     *         },execute);
     *
     *      2)、支持定时任务线程池;设置 TaskSchedulingProperties
     *        spring.task.scheduling.pool.size: 5
     *
     *      3)、让定时任务异步执行
     *          异步任务
     *
     *      解决:使用异步任务 + 定时任务来完成定时任务不阻塞的功能
     *
     */
    @Async
     @Scheduled(cron = "* * * * * ?")
     public void hello() {
         log.info("hello...");
         try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }

     }
}
2023-09-24 17:34:28.015  INFO 15092 --- [         task-3] c.l.g.seckill.scheduled.HelloScheduled   : hello...
2023-09-24 17:34:29.003  INFO 15092 --- [         task-4] c.l.g.seckill.scheduled.HelloScheduled   : hello...
2023-09-24 17:34:30.002  INFO 15092 --- [         task-5] c.l.g.seckill.scheduled.HelloScheduled   : hello...

 

posted on 2023-09-24 17:35  homle  阅读(41)  评论(0编辑  收藏  举报