在启动类上加上注解 @EnableAsync
方法上加上@Async
异步方法和调用的方法不要写在一起
异步方法使用默认线程池会导致OOM
实现:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* @Description: 自定义异步配置类
*/
@Configuration
public class TaskPoolConfig {
/**
* 自定义线程池
* 线程池参数配置,多个线程池实现线程池隔离,@Async注解,默认使用系统自定义线程池,可在项目中设置多个线程池,在异步调用的时候,指明需要调用的线程池名称,比如:@Async("taskName")
**/
@Bean("taskExecutor")
public Executor taskExecutor() {
//返回可用处理器的Java虚拟机的数量 12
int i = Runtime.getRuntime().availableProcessors();
System.out.println("系统最大线程数 : " + i);
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程池大小
executor.setCorePoolSize(16);
//最大线程数
executor.setMaxPoolSize(20);
//配置队列容量,默认值为Integer.MAX_VALUE
executor.setQueueCapacity(99999);
//活跃时间
executor.setKeepAliveSeconds(60);
//线程名字前缀
executor.setThreadNamePrefix("asyncServiceExecutor -");
//设置此执行程序应该在关闭时阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行
executor.setAwaitTerminationSeconds(60);
//等待所有的任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* @Description: 自定义异步方法
*/
@Component
@Slf4j
public class MyAsyncTask {
/**
* @Description: 自定义异步日志记录
* @Datetime: 2023/3/30 14:45
* @param mapper BaseMapper
* @param object 添加数据
**/
@Async("taskExecutor")
public void saveLog(BaseMapper mapper, Object object) {
try {
mapper.insert(object);
} catch (Exception e) {
log.error(mapper + "日志记录失败!");
}
}
}
配置完成后@Async注解就会使用该线程池,有需要的话可以在getAsyncExecutor()方法添加@Bean("线程池名字")注解指定线程池名字,最后在@Async("线程池名字")使用。