创建配置类(自定义出线程池交给spring容器)
package com.cpic.life.policy.server.route.configwls;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class TaskExecutorConfig {
@Value("${spring.task.execution.pool.core-size:5}")
private int corePoolSize;
@Value("${spring.task.execution.pool.max-size:10}")
private int maxPoolSize;
@Value("${spring.task.execution.pool.queue-capacity:5}")
private int queueCapacity;
@Value("${spring.task.execution.thread-name-prefix:god-jiang-task-}")
private String namePrefix;
@Value("${spring.task.execution.pool.keep-alive:60}")
private int keepAliveSeconds;
@Bean
public Executor myAsync() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//最大线程数
executor.setMaxPoolSize(maxPoolSize);
//核心线程数
executor.setCorePoolSize(corePoolSize);
//任务队列的大小
executor.setQueueCapacity(queueCapacity);
//线程前缀名
executor.setThreadNamePrefix(namePrefix);
//线程存活时间
executor.setKeepAliveSeconds(keepAliveSeconds);
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
/**
* 拒绝处理策略
* CallerRunsPolicy():交由调用方线程运行,比如 main 线程。
* AbortPolicy():直接抛出异常。
* DiscardPolicy():直接丢弃。
* DiscardOldestPolicy():丢弃队列中最老的任务。
*/
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//线程初始化
executor.initialize();
return executor;
}
}
创建业务类(具体哪个业务方法需要多线程处理)
package com.cpic.life.policy.server.route.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
@Component
public class ScheduleTask {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Async("myAsync")
public void testAsyncTask(CountDownLatch countDownLatch) {
try {
System.out.println("Spring1自带的线程池" + Thread.currentThread().getName() + "-" + sdf.format(new Date()));
} catch (Exception e) {
e.printStackTrace();
}finally {
countDownLatch.countDown();
}
}
@Async("myAsync")
public void testAsyn() {
try {
System.out.println("Spring2自带的线程池" + Thread.currentThread().getName() + "-" + sdf.format(new Date()));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
测试类(为了保证每个异步线程都处理完,引入CountDownLatch)
package com.cpic.life.policy.server.route.task;
import org.checkerframework.checker.interning.qual.CompareToMethod;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.concurrent.CountDownLatch;
@SpringBootTest
@RunWith(SpringRunner.class)
@ComponentScan(basePackages = {"com.cpic.life.policy.server.route.configwls"})
public class AsyncTest {
@Autowired
private ScheduleTask scheduleTask;
@Test
public void asyncTest01(){
CountDownLatch countDownLatch = new CountDownLatch(20);
for (int i = 0; i < 20; i++) {
scheduleTask.testAsyncTask(countDownLatch);
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果
结束