springboot使用异步线程池执行自定义任务实例

1.介绍

在Spring中存在一个AsyncConfigurer接口,它是一个可以配置异步线程池的接口,因此只需要Java配置文件,实现AsyncConfigurer接口,实现getAsyncExecutor方法返回的线程池,这样Spring就会将使用这个线程池作为其异步调用的线程。为了使得异步可用,Spring还提供一个注解@EnableAsync,如果Java配置文件标注它,那么Spring就会开启异步可用,这样就可以使用注解@Async驱动Spring使用异步调用,下节我们会看到这样的实例。
 
异步实例
使用Java配置定义线程池和启用异步

配置类

package com.springboot.chapter13.config;
/**** imports ****/
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer  {
    
    
    // 定义线程池
    @Override
    public Executor getAsyncExecutor() {
    
    
        // 定义线程池
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数
              taskExecutor.setMaxPoolSize(10);//最大线程数
        taskExecutor.setQueueCapacity(100);//线程队列最大线程数
        taskExecutor.initialize();
        return taskExecutor;
    }
}

 

在代码中,注解@EnableAsync代表开启Spring异步。这样就可以使用@Async驱动Spring使用异步,但是异步需要提供可用线程池,所以这里的配置类还会实现AsyncConfigurer接口,然后覆盖getAsyncExecutor方法,这样就可以自定义一个线程池。因此当方法被标注@Async时,Spring就会通过这个线程池的空闲线程去运行该方法。在getAsyncExecutor方法中创建了线程池,设置了其核心线程、最大线程数、线程队列的限制,然后将线程池初始化,这样异步便可用。

业务层

public interface AsyncService {
    
    //异步服务接口
    public void generateReport();
}

@Service
public class AsyncServiceImpl implements AsyncService {
    
    
@Autowired
private ISongService songService;
    @Override
    @Async//声明异步调用
    public void generateReport() {
    
    
songService.CacheToSql();
        System.out.println(Thread.currentThread().getName());
    }
}

CacheToSql为一个自定义的将redis中数据写入数据库的方法:

  @Override
public int CacheToSql()
{
    
    
    List<UserSong>userSongs = null;
    User principal = (User) SecurityUtils.getSubject().getPrincipal();
    Map<String, Object> likeCountMap = redisService.hGetAll("user:" + principal.getId());
    int insertRecord= 0;
    for(Map.Entry entry:likeCountMap.entrySet()) {
    
    
        String key = (String) entry.getKey();
        String songid = key.split(":")[1];
        Song song = this.getOne(new LambdaQueryWrapper<Song>().eq(Song::getId, songid));

        Integer count = (Integer) entry.getValue();
        UserSong userSong = userSongService.selectByUserAndSong(principal.getId(),song.getId());
        if(Objects.nonNull(userSong))
        {
    
    
            userSong.setPlayCount(count);
            userSongService.saveOrUpdate(userSong);

        }
        else {
    
    
           userSong = new UserSong();
            userSong.setSongId(song.getId());
            userSong.setUserId(principal.getId());
            userSong.setPlayCount(count);
            userSongService.save(userSong);
            insertRecord++;
        }
        System.out.println(userSong);
    }
 //  userSongs.stream().forEach(System.out::println);
    return insertRecord;
}

控制层

 @PostMapping("/play/{songId}")
    public ResponseResult<?> playSong(@PathVariable("songId") Integer songId)
    {
    
    
        songService.playSong(songId);
        asyncService.generateReport();
        return ResponseResult.success();
    }

运行后访问相关路径,查看结果:
在这里插入图片描述
可以看到输出的ThreadPoolTaskExecutor-2为当前正运行的异步线程

猜你喜欢

转载自blog.csdn.net/qq_41358574/article/details/120750077