ThreadPoolTaskExecutor Spring applicationContext.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:task ="http://www.springframework.org/schema/task" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd" > <task:annotation-driven executor ="threadPool" /> <bean id ="threadPool" class ="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" > <property name ="corePoolSize" value ="10" /> <property name ="maxPoolSize" value ="50" /> <property name ="queueCapacity" value ="100" /> <property name ="keepAliveSeconds" value ="30" /> <property name ="waitForTasksToCompleteOnShutdown" value ="true" /> <property name ="allowCoreThreadTimeOut" value ="true" /> <property name ="rejectedExecutionHandler" > <bean class ="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property > </bean > </beans >
MultiThreadDemo-线程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class MultiThreadDemo implements Runnable { private MultiThreadProcessService multiThreadProcessService; public MultiThreadDemo () { } public MultiThreadDemo (MultiThreadProcessService multiThreadProcessService) { this .multiThreadProcessService = multiThreadProcessService; } @Override public void run () { multiThreadProcessService.processSomething(); } }
MultiThreadProcessService-业务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Service public class MultiThreadProcessService { public static final Logger logger = Logger.getLogger(MultiThreadProcessService.class); public void processSomething () { logger.debug("MultiThreadProcessService-processSomething" + Thread.currentThread() + "......start" ); try { Thread.sleep(1000 ); } catch (InterruptedException e) { throw new RuntimeException (e); } logger.debug("MultiThreadProcessService-processSomething" + Thread.currentThread() + "......end" ); } }
测试代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { MultiThreadConfig.class }) public class MultiThreadTest { @Autowired private ThreadPoolTaskExecutor taskExecutor; @Autowired private MultiThreadProcessService multiThreadProcessService; @Test public void test () { int n = 20 ; for (int i = 0 ; i < n; i++) { taskExecutor.execute(new MultiThreadDemo (multiThreadProcessService)); System.out.println("int i is " + i + ", now threadpool active threads totalnum is " + taskExecutor.getActiveCount()); } try { System.in.read(); } catch (IOException e) { throw new RuntimeException (e); } } }
SpringBoot 参考 SpringBoot 线程池的创建、@Async 配置步骤及注意事项
springBoot 启动类的配置 1 2 3 4 5 6 7 8 @ServletComponentScan @SpringBootApplication @EnableAsync public class ClubApiApplication { public static void main (String[] args) { SpringApplication.run(ClubApiApplication.class, args); } }
配置类 ThreadPoolTaskConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import java.util.concurrent.ThreadPoolExecutor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.scheduling.annotation.EnableAsync;import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configuration @EnableAsync public class ThreadPoolTaskConfig { private static final int corePoolSize = 20 ; 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") public ThreadPoolTaskExecutor taskExecutor () { 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; } }
异步方法类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.scheduling.annotation.Async;import org.springframework.stereotype.Service;@Service public class TranTest2Service { Logger log = LoggerFactory.getLogger(TranTest2Service.class); @PostConstruct @Async("taskExecutor") public void sendMessage1 () throws InterruptedException { log.info("发送短信方法---- 1 执行开始" ); Thread.sleep(5000 ); log.info("发送短信方法---- 1 执行结束" ); } @PostConstruct @Async("taskExecutor") public void sendMessage2 () throws InterruptedException { log.info("发送短信方法---- 2 执行开始" ); Thread.sleep(2000 ); log.info("发送短信方法---- 2 执行结束" ); } }
调用 OrderTaskServic.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Service public class OrderTaskServic { @Autowired private TranTest2Service tranTest2Service; public void orderTask () throws InterruptedException { this .cancelOrder(); tranTest2Service.sendMessage1(); tranTest2Service.sendMessage2(); } public void cancelOrder () throws InterruptedException { System.out.println("取消订单的方法执行------开始" ); System.out.println("取消订单的方法执行------结束 " ); } }
注意事项 如下方式会使 @Async 失效
异步方法使用 static 修饰
异步类没有使用 @Component 注解(或其他注解)导致 spring 无法扫描到异步类
异步方法不能与被调用的异步方法在同一个类中
类中需要使用 @Autowired 或 @Resource 等注解自动注入,不能自己手动 new 对象
如果使用 SpringBoot 框架必须在启动类中增加 @EnableAsync 注解