首先配置线程池,注意几个重要的参数
-
corePoolSize(核心线程数):指定线程池中核心线程的数量。核心线程会一直存活,即使它们处于空闲状态,除非设置了allowCoreThreadTimeOut参数。在没有任务需要执行时,核心线程也不会被回收。
-
maxPoolSize(最大线程数):表示线程池中允许的最大线程数量。当任务队列满了并且正在运行的线程数少于最大线程数时,会创建新的线程来执行任务。如果已经达到最大线程数并且任务队列也已满,新的任务将被拒绝。
-
queueCapacity(任务队列容量):定义了线程池中的任务队列的容量。当任务提交到线程池中,但核心线程数已满并且任务队列也已满时,会继续创建新的线程,直到达到最大线程数。如果任务队列已满,且线程池中的线程数已达到最大线程数,则会执行拒绝策略。
-
keepAliveTime(线程空闲时间):当线程池中的线程数大于核心线程数时,空闲线程的存活时间。即如果线程空闲时间超过keepAliveTime时,线程会被终止并从线程池中移除,以减少资源消耗。
-
allowCoreThreadTimeOut(允许核心线程超时):当设置为true时,允许核心线程在空闲时间超过keepAliveTime后被终止并从线程池中移除。
package com.qcby.adru.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.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync // 允许使用异步方法
public class ThreadPoolConfig {
@Bean
public ExecutorService executorService() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
// 设置核心线程数
threadPoolTaskExecutor.setCorePoolSize(16);
// 设置最大线程数
threadPoolTaskExecutor.setMaxPoolSize(16);
// 设置任务队列大小
threadPoolTaskExecutor.setQueueCapacity(2000);
// 设置线程名称前缀
threadPoolTaskExecutor.setThreadNamePrefix("threadPoolTaskExecutor-->");
// 设置拒绝策略.当工作队列已满,线程数为最大线程数的时候,接收新任务交给主线程执行
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化线程池
threadPoolTaskExecutor.initialize();
return Executors.newSingleThreadExecutor();
}
}
如何让一个方法成为多线程呢?
实例分析:比如我想要开多线程进行插入数据,这个时候可以按照下面的方式去写,这种写法呢是创建了一个任务丢给了操作系统,它会被放进任务队列中,等待线程去拿取任务并执行,但是我们这样只是放了一个任务进去,也只会有一个线程进行调用
@Async
public void test(User s){
AtomicInteger pageNum = new AtomicInteger(1);
AtomicReference<Boolean> flag = new AtomicReference<>(true);
CompletableFuture.runAsync(()->{
try {
userService.save(s);
} catch (Exception e) {
e.printStackTrace();
}
},executorService);
}
}
可以创建多个实例进行实现:下面的代码就是创建了三个任务,等待空闲的线程进行调用任务,当然可以使用for循环实现,(不建议采用while,如果停止的逻辑出现问题,就容易引发死循环)
@Async
public void test(User s){
AtomicInteger pageNum = new AtomicInteger(1);
AtomicReference<Boolean> flag = new AtomicReference<>(true);
CompletableFuture.runAsync(()->{
try {
userService.save(s);
} catch (Exception e) {
e.printStackTrace();
}
},executorService);
}
CompletableFuture.runAsync(()->{
try {
userService.save(s);
} catch (Exception e) {
e.printStackTrace();
}
},executorService);
}
CompletableFuture.runAsync(()->{
try {
userService.save(s);
} catch (Exception e) {
e.printStackTrace();
}
},executorService);
}
}