springboot使用异步线程池执行自定义任务实例
原创
©著作权归作者所有:来自51CTO博客作者TvT~的原创作品,请联系作者获取转载授权,否则将追究法律责任
文章目录
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为当前正运行的异步线程