最近做一个文档转换功能比较耗时,所以用到了线程池来处理。
Spring管理线程池有两种方式,
第一种是XML配置文件配置线程池的Bean,然后在用的时候像Controller引用Service的Bean一样的引用线程池对象就可以了。
第二种方式是无配置文件,就是全是java代码和注解就实现了。
这里只讲解第二种方式。
总共分三步实现吧,
第一步:写一个配置线程池的java类,并在类上加上注解,如下代码:
@Configuration @EnableAsync public class MutiThreadConfig { /** * 最闲时线程数量 */ private int corePoolSize = 10; /** * 最忙时线程数量 */ private int maxPoolSize = 30; /** * 线程队列缓存大小 */ private int queueCapacity = 8; /** * 线程最大空闲时间 */ private int keepAlive = 60; @Bean public Executor myExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setThreadNamePrefix("mqExecutor-"); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //对拒绝task的处理策略 executor.setKeepAliveSeconds(keepAlive); executor.initialize(); return executor; } }
第二步:启动服务时实例化线程池对象,即在启动的类上加如下第一行注解即可。
@EnableAsync //启动线程池 @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
第三步:写需要耗时的任务,这里写在Service的实现类里,把耗时任务单独抽成一个方法(如例子中mytask()方法),如果整个service都需要异步执行,直接把注解@Async加在Service的方法上也可以,如doMutiExcute()方法。
@Service public class UserServiceImpl implements UserService { @Override public User getUser(String id) { User user = new User(); user.setAge(10); user.setName("zhc"); user.setId(id); return user; } @Override public String doMutiExcute(String name) { Long threadId = myTask(); return "总共运行了"+threadId+"个线程"; } @Async public Long myTask() { Long threadId = Long.MIN_VALUE; try { threadId = Thread.currentThread().getId(); System.out.println("当前线程ID="+threadId); Thread.sleep(2000);//设置耗时任务 }catch (InterruptedException e){ e.printStackTrace(); } return threadId; } }
测试:
写一个controller调用service
@RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/getUser") public User getUser(@RequestParam(value="id", defaultValue="1") String id) { return userService.getUser(id); } @RequestMapping("/doExcute") public String excuteMutiThread(String name){ return userService.doMutiExcute(name); } }
启动服务,在浏览器访问http://localhost:8080/doExcute?name=zhc
后面打印显示了用不同线程ID执行任务
到此,无配置文件化的线程池管理完成。