多线程一直是工做或面试过程当中的高频知识点,今天给你们分享一下使用 ThreadPoolTaskExecutor 来自定义线程池和实现异步调用多线程。面试
本文采用 Executors 的工厂方法进行配置。spring
在项目的 resources 目录下建立 executor.properties 文件,并添加以下配置:多线程
# 异步线程配置
# 核心线程数
async.executor.thread.core_pool_size=5
# 最大线程数
async.executor.thread.max_pool_size=8
# 任务队列大小
async.executor.thread.queue_capacity=2
# 线程池中线程的名称前缀
async.executor.thread.name.prefix=async-service-
# 缓冲队列中线程的空闲时间
async.executor.thread.keep_alive_seconds=100复制代码
@Configuration
// @PropertySource是找的target目录下classes目录下的文件,resources目录下的文件编译后会生成在classes目录
@PropertySource(value = {"classpath:executor.properties"}, ignoreResourceNotFound=false, encoding="UTF-8")
@Slf4j
public class ExecutorConfig {
@Value("${async.executor.thread.core_pool_size}")
private int corePoolSize;
@Value("${async.executor.thread.max_pool_size}")
private int maxPoolSize;
@Value("${async.executor.thread.queue_capacity}")
private int queueCapacity;
@Value("${async.executor.thread.name.prefix}")
private String namePrefix;
@Value("${async.executor.thread.keep_alive_seconds}")
private int keepAliveSeconds;
@Bean(name = "asyncTaskExecutor")
public ThreadPoolTaskExecutor taskExecutor() {
log.info("启动");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数
executor.setCorePoolSize(corePoolSize);
// 最大线程数
executor.setMaxPoolSize(maxPoolSize);
// 任务队列大小
executor.setQueueCapacity(queueCapacity);
// 线程前缀名
executor.setThreadNamePrefix(namePrefix);
// 线程的空闲时间
executor.setKeepAliveSeconds(keepAliveSeconds);
// 拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 线程初始化
executor.initialize();
return executor;
}
}复制代码
一般 ThreadPoolTaskExecutor 是和 @Async 一块儿使用。在一个方法上添加 @Async 注解,代表是异步调用方法函数。@Async 后面加上线程池的方法名或 bean 名称,代表异步线程会加载线程池的配置。app
@Component
@Slf4j
public class ThreadTest {
/**
* 每10秒循环一次,一个线程共循环10次。
*/
@Async("asyncTaskExecutor")
public void ceshi3() {
for (int i = 0; i <= 10; i++) {
log.info("ceshi3: " + i);
try {
Thread.sleep(2000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}复制代码
备注:必定要在启动类上添加 @EnableAsync 注解,这样 @Async 注解才会生效。异步
// 在启动类上添加 @EnableScheduling 注解
@SpringBootApplication
@EnableScheduling
public class SpringBootStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootStudyApplication.class, args);
}
}复制代码
// @Component 注解将定时任务类归入 spring bean 管理。
@Component
public class listennerTest3 {
@Autowired
private ThreadTest t;
// 每1分钟执行一次ceshi3()方法
@Scheduled(cron = "0 0/1 * * * ?")
public void run() {
t.ceshi3();
}
}复制代码
ceshi3() 方法调用线程池配置,且异步执行。async
@Component
@Slf4j
public class ThreadTest {
/**
* 每10秒循环一次,一个线程共循环10次。
*/
@Async("asyncTaskExecutor")
public void ceshi3() {
for (int i = 0; i <= 10; i++) {
log.info("ceshi3: " + i);
try {
Thread.sleep(2000 * 5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}复制代码
经过继承 CommandLineRunner 类实现。ide
@Component
public class ListennerTest implements CommandLineRunner {
@Autowired
private ThreadTest t;
@Override
public void run(String... args) {
for (int i = 1; i <= 10; i++) {
t.ceshi();
}
}
}复制代码
@Component
@Slf4j
public class ThreadTest {
@Async("asyncTaskExecutor")
public void ceshi() {
log.info("ceshi");
}
} 复制代码
还能够经过接口的形式来异步调用多线程:函数
@RestController
@RequestMapping("thread")
public class ListennerTest2 {
@Autowired
private ThreadTest t;
@GetMapping("ceshi2")
public void run() {
for (int i = 1; i < 10; i++) {
t.ceshi2();
}
}
}复制代码
@Component
@Slf4j
public class ThreadTest {
@Async("asyncTaskExecutor")
public void ceshi2() {
for (int i = 0; i <= 3; i++) {
log.info("ceshi2");
}
}
} 复制代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class ThreadRunTest {
@Autowired
private ThreadTest t;
@Test
public void thread1() {
for (int i = 1; i <= 10; i++) {
t.ceshi4();
}
}
}复制代码
@Component
@Slf4j
public class ThreadTest {
@Async("asyncTaskExecutor")
public void ceshi4() {
log.info("ceshi4");
}
}复制代码
以上主要介绍了 ThreadPoolTaskExecutor 线程池的配置、使用、相关注解的意义及做用,也简单介绍了使用 @Async 来异步调用线程,最后又列举了多线程的使用场景,并配上了代码示例。但愿你们喜欢。工具