??在项目中使用多线程时,通常建议使用线程池而不是直接使用 new Thread 的方式来创建线程。下面是一些原因:
??ThreadPoolTaskExecutor 是 Spring 框架提供的一个实现了 Executor 和 AsyncTaskExecutor 接口的线程池任务执行器。它是 Spring 提供的内置线程池实现,用于在应用程序中管理线程池并执行异步任务。
??ThreadPoolTaskExecutor 具有一些常用的线程池配置属性,例如核心线程数、最大线程数、线程池队列容量、空闲线程的存活时间等,可以根据应用程序的需求进行灵活的配置。
@Configuration
public class ThreadPoolTaskConfig {
// 核心线程数(默认线程数)
private static final int CORE_POOL_SIZE = 20;
// 最大线程数
private static final int MAX_POOL_SIZE = 100;
// 允许线程空闲时间(单位:默认为秒)
private static final int KEEP_ALIVE_TIME = 10;
// 缓冲队列大小
private static final int QUEUE_CAPACITY = 200;
// 线程池名前缀
private static final String THREAD_NAME_PREFIX = "my-Async-";
@Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名
public ThreadPoolTaskExecutor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setKeepAliveSeconds(KEEP_ALIVE_TIME);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
// 线程池对拒绝任务的处理策略
// CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 初始化
executor.initialize();
return executor;
}
}
@Resource(name = "taskExecutor")
private ThreadPoolTaskExecutor taskExecutor;
public void doTask() throws Exception {
//execute方法
taskExecutor.execute(() -> testResult());
//submit方法
Future<Integer> submit = taskExecutor.submit(() -> testResult());
System.out.println(submit.get());
}
public static Integer testResult() {
return 10;
}
??execute 方法是 Executor 接口中定义的方法,它只能执行 Runnable
任务,并且没有返回值。如果任务执行失败,你无法得到任何有用的信息。
??submit 方法是 ExecutorService 接口中定义的方法,它可以执行 Runnable
任务或者 Callable
任务,并且它会返回一个 Future 对象,通过 Future 对象你可以获得任务执行的结果或者异常信息。
??基本上来说,submit 方法比 execute 方法更加灵活和功能更加完善。如果你需要获取任务执行的结果,或者需要更好地处理任务执行时可能出现的异常,建议使用 submit 方法。
??@Async
是一个注解,用于指示方法应该以异步方式执行。它是 Spring 框架提供的一个特性,可以方便地实现异步方法调用。
??当使用 @Async
注解标记一个方法时,Spring 将会创建一个线程池或者使用默认的线程池来执行该方法。这样,方法将会在一个单独的线程中异步执行,而不会阻塞当前线程。
??要使 @Async
注解生效,还需要在 Spring 配置中启用异步支持。你可以通过在配置类上添加@EnableAsync
注解来实现
@Configuration
@EnableAsync
public class ThreadPoolTaskConfig {
......
}
??通过上述配置,Spring 将会在启动时自动扫描使用@Async
注解的方法,并为其创建相应的代理,从而实现异步执行。
@Async("taskExecutor")
public void doTask() throws Exception {
log.info("开始做任务");
long start = System.currentTimeMillis();
Thread.sleep(5000);
long end = System.currentTimeMillis();
log.info("完成任务,耗时:" + (end - start) + "毫秒");
}
@Autowired
public AsyncTask asyncDemo;
@GetMapping("/async")
public void getResult() throws Exception {
for (int i = 0; i < 5; i++) {
asyncDemo.doTask();
}
}