背景:
用户添加一个ak,需要向若干个url发送请求,因此需要采用多线程的方式提高效率
方案:
采用spring提供的ThradPoolTaskExecutor类创建线程池,使用@Async创建异步任务,@EnableAsync开启异步,部分代码如下所示:
@Configuration @EnableAsync public class ThreadPoolConfig { private static final int corePoolSize = 10; // 核心线程数(默认线程数) private static final int maxPoolSize = 100; // 最大线程数 private static final int keepAliveTime = 10; // 允许线程空闲时间(单位:默认为秒) private static final int queueCapacity = 200; // 缓冲队列数 private static final String threadNamePrefix = "Async-Service-"; // 线程池名前缀 ? @Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名 public ThreadPoolTaskExecutor getAsyncExecutor(){ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setKeepAliveSeconds(keepAliveTime); executor.setThreadNamePrefix(threadNamePrefix); ? // 线程池对拒绝任务的处理策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 初始化 executor.initialize(); return executor; } } ? @Component public class Agent{ @Autowired private RestTemplate restTemplate; @Async public void sendMsg(Ak ak, String url) { restTemplate.exchange(..); logger.info("向{}发送成功", url); } } ? @Component public class MyController{ public void handleMsg() { for(String url : urls) { agent.sendMsg(); } } }
问题:
控制台不输出restTemplate.execute()的日志,debug也找不到对应的问题
踩坑:
RestTemplate采用的是同步方式,不能执行异步任务
这种情况下,使用同步比较好,可以使用Feature feature = executor.submit(Runnable task)
如果还是想要用异步的方式该怎么办呢?
spring提供了AsyncRestTemplate提供异步请求方式,只需要将restTemplate更换为asyncRestTemplate即可
扩展:
1、execute()和submit()二者的区别
后者有返回值,可以获得执行结果相关信息.get()方法会阻塞当前线程直到任务完成,使用get(long timeout, TimeUnit unit)设置超时时间,阻塞线程一段时间后立即返回(任务可能没完成)
threadPool.execute( ()->{ //TODO task }); ? Future<Object> future = threadPool.submit(){ ()->{ //TODO }; } try{ Object obj = future.get(); }catch(Exception ex) { // }finally{ // }
2、什么场景下分别使用异步和同步?
1、不涉及共享资源,或对共享资源只读,即非互斥操作
2、没有时序上的严格关系
3、不需要原子操作,或可以通过其他方式控制原子性
4、常用于IO操作等耗时操作,因为比较影响客户体验和使用性能
5、不影响主线程逻辑
?
同步的好处:
1、同步流程对结果处理通常更为简单,可以就近处理。
2、同步流程对结果的处理始终和前文保持在一个上下文内。
3、同步流程可以很容易捕获、处理异常。
4、同步流程是最天然的控制过程顺序执行的方式。
异步的好处:
1、异步流程可以立即给调用方返回初步的结果。
2、异步流程可以延迟给调用方最终的结果数据,在此期间可以做更多额外的工作,例如结果记录等等。
3、异步流程在执行的过程中,可以释放占用的线程等资源,避免阻塞,等到结果产生再重新获取线程处理。
4、异步流程可以等多次调用的结果出来后,再统一返回一次结果集合,提高响应效率。
总结:
【1】这种就属于积累性的问题,多看多想