ThreadpoolTaskExecutor相对于ThreadpoolExecutor来说,是使用了ThreadPoolExecutor并增强,扩展了更多特性。它是Spring提供的线程池,帮助我们快速创建一个可用的线程池来使用。
@Async是Spring的注解,可以加在类或方法上。通俗的来讲,如果加上了这个注解,那么该类或者该方法在使用时将会进行异步处理,也就是创建一个线程来实现这个类或者方法,实现多线程。
使用1、配置线程池
package com.czf.connect.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.ThreadPoolExecutor; @EnableAsync //表示开启多线程 @Configuration public class ThreadPoolConfig { private static final int CORE_POOL_SIZE = 20; private static final int MAX_POOL_SIZE = 40; private static final int QUEUE_CAPACITY = 200; private static final int KEEP_ALIVE_SEConDS = 60; @Bean(name = "threadPoolTaskExecutor") //ThreadPoolTaskExecutor不会自动创建ThreadPoolExecutor,需要手动调initialize才会创建。如果@Bean就不需手动,会自动InitializingBean的afterPropertiesSet来调initialize public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); // 设置线程池最大线程数 executor.setMaxPoolSize(MAX_POOL_SIZE); // 线程池活跃的线程数 executor.setCorePoolSize(CORE_POOL_SIZE); // 设置线程队列最大线程数 executor.setQueueCapacity(QUEUE_CAPACITY); // 线程池维护线程所允许的空闲时间 executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS); executor.setThreadNamePrefix("task-async");//线程前缀名称 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } }
2、需要异步 *** 作的方法或类:
@Slf4j @Component //将该类注入到容器中 public class AsyncTest { @Async("threadPoolTaskExecutor") //调用该线程池 public void task() throws InterruptedException { Thread.sleep(4000); log.info("task异步处理"); } }
3、测试类
@Slf4j @RestController public class PoolTest { @Autowired private AsyncTest asyncTest; @RequestMapping("/pool") public void poolTest() throws InterruptedException { log.info("主线程开始"); asyncTest.task(); log.info("主线程结束"); } }
4、结果:
可以看出是由不同的线程执行。
1、@Async需要在Spring环境下才能启动,使用的是AOP动态代理技术
2、@Async使用的是动态代理来实现异步调用,因此不能够在同一个类中进行调用。方法一定要从另一个类中调用,也就是从类的外部调用,类的内部调用是无效的,有可能因为调用方法的是对象本身而不是代理对象,因为没有经过Spring容器。
3、注解的方法必须是public方法
4、需要在@SpringBootApplication启动类或者@configure注解类上 添加注解@EnableAsync启动多线程注解。
5、@Async就会对标注的方法开启异步多线程调用,注意,这个方法的类一定要交给spring容器来管理。
6、异步方法使用注解@Async的返回值只能为void或者Future。
有返回值的异步处理上述方法实现的是无返回值的异步 *** 作,接下来实现的是有返回值的异步 *** 作,即返回值为Future。
异步方法
@Async("threadPoolTaskExecutor") public Futuretask1() throws InterruptedException { log.info("异步处理开始"); Thread.sleep(2000); return new AsyncResult ("异步处理"); } @Async("threadPoolTaskExecutor") public Future task2() throws InterruptedException { log.info("异步处理开始"); User2 user2 = new User2(); user2.setName("zhangsan"); user2.setId(1); Thread.sleep(2000); return new AsyncResult (user2); }
接口实现
@RequestMapping("/pool1") public String poolTest1() throws InterruptedException, ExecutionException { log.info("主线程开始"); FuturestringFuture = asyncTest.task1(); log.info("主线程结束"); Thread.sleep(2000); log.info("{}",stringFuture.get()); return stringFuture.get(); } @RequestMapping("/pool2") public User2 poolTest2() throws InterruptedException, ExecutionException { log.info("主线程开始"); Future stringFuture = asyncTest.task2(); log.info("主线程结束"); Thread.sleep(2000); log.info("{}",stringFuture.get()); return stringFuture.get(); }
poolTest1方法:
poolTest2方法:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)