文章目录

  • ​​1.介绍​​
  • ​​配置类​​
  • ​​业务层​​
  • ​​控制层​​

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();
}

运行后访问相关路径,查看结果:

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


可以看到输出的ThreadPoolTaskExecutor-2为当前正运行的异步线程