读《Spring Cloud微服务全栈技术与案例解析》的笔记二--使用线程池实现异步
感谢读者
非常感谢微信读者,意想不到的收获了大约20+的阅读量,虽然是个小小的进步,但还是控制不住内心的激动,这种小小的成就感让我精神起来了。
异步与线程池
异步调用: 不用等待执行结果的返回,就继续往下执行逻辑 同步调用: 必须等待执行结果的返回,才能继续往下执行逻辑
往往我门需要额外启动线程,来完成异步调用,很典型的做法就是使用线程池,去启动一段代码。
我们在控制器Controller增加一个 taskDemo方法,请求路径为/task ,代码如下
@RequestMapping("/task")
private String taskDemo(){
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.execute(()->{
try {
// 业务代码
System.out.println("executing task");
}
catch (Exception ex){
ex.printStackTrace();
}
});
return "error";
}
报错问题
加完以后发现会有个报错 ‘线程池不允许使用Executors去创建...’
完整信息如下:
Inspection '线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。' options
可以看到是提示我们采用ThreadPoolExecutor的方式去创建
修改后代码如下:
@RequestMapping("/task")
private String taskDemo(){
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,
10,
10,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(1));
threadPoolExecutor.execute(()->{
try {
// 业务代码
System.out.println("executing task");
}
catch (Exception ex){
ex.printStackTrace();
}
});
return "error";
}
构造方法
通过IDE,我们可以看到 ThreadPoolExecutor这个类有四个构造方法
构造方法一
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
构造方法二
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
构造方法三
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
构造方法四
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
可见最简单的就是构造方法一了
我们不需要定制线程,因此使用默认的ThreadFactory就可以了。
我们这里也不需要处理线程池中任务被拒绝的情况,使用默认的处理行为(直接抛出RejectedExecutionException异常,阻止系统正常运行)即可
所以我们选择参数最少的构造函数,去创建对象。
异步注解
上面是通过线程池来创建异步调用方法,还有一种通过注解的方式来创建
注解: @Async
示例代码如下
@RequestMapping("/taskAsync") @Async public String taskAsync(){
System.out.println("executing taskAsync");
return "taskAsync";
}
这里如果方法的修饰符为private 可能会报错,出现红色波浪线
建议使用public 或者是protected关键字。
要使用这个注解,在启动类上需要增加@EnableAsync注解
关于《Spring Cloud微服务全栈技术与案例解析》 这本书,一共有300多页的内容,从单体应用的基础到微服务的各个组件,从负载均衡到分布式事务都有非常详细的讲解,如果您对此书感兴趣,可以加我微信(yeegee2024)免费领书