本文介绍异步线程调用的两种方式:注解实现和WebAsyncTask对象。
基于spring boot快速搭建的一个项目
线程池的好处就不多说了,不过如果不想创建线程池的话也可以继续下去,直接跳过这步就行。
新建一个配置文件,直接复制下面的就行,具体参数都有写注释,可以根据自己的需要调整。
注解@Configuration就不多说了;
注解@EnableAsync是开启异步,开启异步后才能完美使用@Asynz进行异步调用;
注解 @Bean是将线程池对象交给spring容器管理,在创建WebAsyncTask对象的时候需要传入一个线程池对象,关于WebAsyncTask对象在后面介绍
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池配置类
* tasks :每秒的任务数
* taskcost:每个任务花费时间,假设为0.1s
* responsetime:系统允许容忍的最大响应时间,假设为1s
*
*/
@Configuration
@EnableAsync // 开启异步
public class ThreadPoolConfig {
/**
* 每秒需要多少个线程处理?
*/
private int corePoolSize = 3;
/**
* 线程池维护线程的最大数量
*/
private int maxPoolSize = 3;
/**
* 缓存队列
*/
private int queueCapacity = 10;
/**
* 允许的空闲时间
* 默认为60
*/
private int keepAlive = 100;
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(corePoolSize);
// 设置最大线程数
executor.setMaxPoolSize(maxPoolSize);
// 设置队列容量
executor.setQueueCapacity(queueCapacity);
// 设置允许的空闲时间(秒)
// executor.setKeepAliveSeconds(keepAlive);
// 设置默认线程名称
executor.setThreadNamePrefix("thread-");
// 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
接口
/**
* 线程池测试
*/
public interface AsyncService {
void executeAsync();
}
实现类
@Async放在方法上表示这个方法要异步调用,放在类上面,表示这个类的所有方法可以异步调用
/**
1. 线程池测试代码
*/
@Service
public class AsyncServiceImpl implements AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class);
@Override
@Async
public void executeAsync() {
logger.info("start executeAsync");
try {
Thread.currentThread().sleep(10000);
System.out.println("当前运行的异步线程名称:" + Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
logger.info("end executeAsync");
}
}
@RestController
public class ThreadController {
@Autowired
private AsyncService asyncService;
@Autowired
private TaskExecutor taskExecutor;
/**
* 测试 异步注解:@Asynz
*
* @return
*/
@GetMapping("/thread")
public IResult thread() {
//调用service层的任务
asyncService.executeAsync();
System.out.println("当前运行的处理线程名称:" + Thread.currentThread().getName());
return JsonResult.success(Thread.currentThread().getName());
}
}
在图中,如果任务二与这个请求中其他任务没有关系,那么使用这种异步方式就可以很好的减少请求花费的时间了
// 引入线程池对象
@Autowired
private TaskExecutor taskExecutor;
/**
* 测试 异步任务:WebAsyncTask
*
* @return
*/
@GetMapping("/threadTestWebAsyncTask")
public WebAsyncTask<IResult> threadTestWebAsyncTask() {
WebAsyncTask<IResult> task = new WebAsyncTask<IResult>(1 * 1000L, (ThreadPoolTaskExecutor) taskExecutor, () -> {
System.err.println("异步线程开始:" + Thread.currentThread().getName());
Thread.sleep(3 * 1000L);
System.err.println("异步线程:" + Thread.currentThread().getName());
return JsonResult.success("task执行完成!");
});
// 超时会走这
task.onTimeout(() -> {
return JsonResult.error("task执行超时!!!!!");
});
// 异常会走这
task.onError(() -> {
return JsonResult.error("task执行异常!!!!!");
});
// 任务执行完成时调用该方法
task.onCompletion(() -> {
System.err.println("task执行完成啦!");
});
System.out.println("当前运行的处理线程名称:" + Thread.currentThread().getName());
return task;
}
本文地址:https://blog.csdn.net/qq_37271924/article/details/107253411
如对本文有疑问, 点击进行留言回复!!
Mybatis PersistenceException异常:Error building SqlSession The error may exist in SQL Mapper Configur
MyBatis——动态SQL语句——if标签和where标签复合使用
网友评论