百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

深入理解并发编程:使用任务执行器和调度器,Spring任务执行器

ccwgpt 2024-09-29 09:55 32 浏览 0 评论

Spring任务执行器

在日常开发过程中,想要处理长时间运行的任务,对于任何应用程序开发而言都不是一件容易实现的事情。

有时候,我们需要异步执行任务或在特定延迟之后执行任务,这时候就可以通过Spring的任务执行器和任务调度器来实现这一目标。

Spring框架通过TaskExecutor和TaskScheduler接口引入了对异步执行和任务调度的抽象。

在本节中,我们先来讨论TaskExecutor。

TaskExecutor应用方式

Spring提供TaskExecutor接口作为Executor的抽象,并内置了一组非常有用的实现类。其中最具有代表性的是SimpleAsyncTaskExecutor,该类在Spring框架内部也得到了广泛应用。SimpleAsyncTaskExecutor会启动一个新线程并异步执行任务,但不会重用线程。

让我们看一个在Spring应用程序中使用SimpleAsyncTaskExecutor执行异步任务的简单示例。我们可以通过如代码清单11-5所示的方式在Spring应用程序中注入SimpleAsyncTaskExecutor。

代码清单11-5 注入SimpleAsyncTaskExecutor实现代码

@Bean

AsyncTaskExecutor taskExecutor() {

SimpleAsyncTaskExecutor taskExecutor = new

SimpleAsyncTaskExecutor();

return taskExecutor;

}

这里的AsyncTaskExecutor是TaskExecutor接口的子接口,而SimpleAsyncTaskExecutor实现了该接口。然后,我们可以构建一个AsyncTask,并通过AsyncTaskExecutor来异步执行任务,如代码清单11-6所示。

代码清单11-6 AsyncTask实现代码

public class AsyncTask {

@Autowired

private AsyncTaskExecutor executor;

public void runTasks() throws Exception {

for (int i = 1; i <= 5; i++) {

Runnable task = new SpringTask(" " + i);

executor.execute(task);

}

}

}

这里我们复用了前面所创建的SpringTask。执行这段代码,我们会在控制台中得到如代码清单11-7所示的输出结果。显然,基于SimpleAsyncTaskExecutor,任务与线程之间应该是一对一的执行关系。

代码清单11-7 Simple AsyncTaskExecutor执行日志

INFO SpringTask:15 - SimpleAsyncTaskExecutor-3, Execute Task = 3

INFO SpringTask:15 - SimpleAsyncTaskExecutor-1, Execute Task = 1

INFO SpringTask:15 - SimpleAsyncTaskExecutor-2, Execute Task = 2

INFO SpringTask:15 - SimpleAsyncTaskExecutor-5, Execute Task = 5

INFO SpringTask:15 - SimpleAsyncTaskExecutor-4, Execute Task = 4

INFO SpringTask:17 - SimpleAsyncTaskExecutor-2, End

INFO SpringTask:17 - SimpleAsyncTaskExecutor-4, End

INFO SpringTask:17 - SimpleAsyncTaskExecutor-3, EndINFO SpringTask:17 - SimpleAsyncTaskExecutor-5, End

INFO SpringTask:17 - SimpleAsyncTaskExecutor-1, End

TaskExecutor运行原理

介绍完Spring任务执行器的使用方式之后,我们来进一步分析它的实现原理。同样,我们还是以前面介绍的SimpleAsyncTaskExecutor为例展开讨论。SimpleAsyncTaskExecutor的类层结构如图11-1所示。

这里的TaskExecutor和AsyncTaskExecutor都比较好理解,我们直接看它们的接口定义,如代码清单11-8所示。

在图11-1中可以看到,AsyncListenableTaskExecutor又扩展了AsyncTaskExecutor,添加了可以返回ListenableFuture对象的方法,如代码清单11-9所示。

ListenableFuture是Spring为开发人员提供的一个工具类,它是Future的子接口,可在任务提交后添加回调,定义如代码清单11-10所示。

代码清单11-8 TaskExecutor和AsyncTaskExecutor接口定义代码

public interface TaskExecutor extends Executor {

@Override

void execute(Runnable task);

}

public interface AsyncTaskExecutor extends TaskExecutor {

void execute(Runnable task, long startTimeout);

Future<?> submit(Runnable task);

<T> Future<T> submit(Callable<T> task);

}

代码清单11-9 TaskExecutor和AsyncTaskExecutor接口定义代码

public interface AsyncListenableTaskExecutor extends AsyncTaskExecutor

{

ListenableFuture<?> submitListenable(Runnable task);

<T> ListenableFuture<T> submitListenable(Callable<T> task)

}

代码清单11-10 ListenableFuture接口定义代码

public interface ListenableFuture<T> extends Future<T> {

void addCallback(ListenableFutureCallback<? super T> callback);

void addCallback(SuccessCallback<? super T> successCallback,

FailureCallback failureCallback);

default CompletableFuture<T> completable() {

CompletableFuture<T> completable = newDelegatingCompletableFuture<>(this);

addCallback(completable::complete,

completable::completeExceptionally);

return completable;

}

}

接下来,我们来看AsyncListenableTaskExecutor中的execute()方法,如代码清单11-11所示。

代码清单11-11 AsyncListenableTaskExecutor的execute()方法代码

@Override

public void execute(Runnable task, long startTimeout) {

Assert.notNull(task, "Runnable must not be null");

//使用包装器包装任务

Runnable taskToUse = (this.taskDecorator != null ?

this.taskDecorator.decorate(task) : task);

//启用限流器来执行任务

if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {

this.concurrencyThrottle.beforeAccess();

doExecute(new ConcurrencyThrottlingRunnable(taskToUse));

}

//不启用限流器来执行任务

else {

doExecute(taskToUse);

}

}

这里引出了限流器(Throttle)的概念,限流器的作用是在线程执行的并发度达到阈值时让后续的线程处于阻塞等待。这是Spring TaskExecutor设计上的一个亮点,基本思想如图11-2所示。

通过图11-2,我们不难看出限流器在线程执行之前进行了对并发限制的

判断,如果需要限流就阻塞线程。而一旦任务执行完成,就会唤醒正在等待

的线程继续执行任务。

而真正执行任务的doExecute()方法比较简单,我们从线程工厂ThreadFactory获取线程,或者直接创建一个新的线程进行执行即可,如代码清单11-12所示。

代码清单11-12 AsyncListenableTaskExecutor的doExecute()方法代码

protected void doExecute(Runnable task) {

Thread thread = (this.threadFactory != null ?

this.threadFactory.newThread(task) : createThread(task));

thread.start();

}

本文给大家讲解的内容是并发编程:使用任务执行器和调度器,Spring任务执行器

  • 下文给大家讲解的是并发编程:使用任务执行器和调度器, Spring任务调度器

相关推荐

如何高效实现API接口的自动化测试?

实现API接口的自动化测试是一个多步骤的过程,涉及需求分析、测试用例设计、环境搭建、脚本编写、执行测试、结果分析和持续集成等多个环节。选择合适的工具和框架也是成功的关键。嘿,咱来聊聊实现API接口自动...

总结100+前端优质库,让你成为前端百事通

1年多时间,陆陆续续整理了一些常用且实用的开源项目,方便大家更高效地学习和工作.js相关库js常用工具类「lodash」一个一致性、模块化、高性能的JavaScript实用工具库。「xij...

混合开发到底怎么个混法?(混合开发rn)

引言最近几年混合开发越来越火,从PhoneGap到Cordova到Ionic,再到ReactNative,到Flutter。同时在搜索引擎中诸如IonicVSReactNativeRN和Weex+...

无所不能,将 Vue 渲染到嵌入式液晶屏

该文章转载自公众号@前端时刻,https://mp.weixin.qq.com/s/WDHW36zhfNFVFVv4jO2vrA前言之前看了雪碧大佬的将React渲染到嵌入式液晶屏觉得很有意思,R...

【直接收藏】前端 VUE 高阶面试题(一)

说说vue动态权限绑定渲染列表(权限列表渲染)首先请求服务器,获取当前用户的权限数据,比如请求this.$http.get("rights/list");获取到权限数据之后,在列表中...

Vue采用虚拟DOM的目的是什么?(vue2 虚拟dom)

虚拟DOM更新其实效率并不像大家想象中的那么高,而且React官方也从来没说过虚拟DOM效率有多高,相反React虚拟DOM的实现也不是所有虚拟DOM产品中最好的。但是通过虚拟D...

什么是 JavaScript?(什么是党的旗帜)

本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!作者|慕课网精英讲师然冬JavaScript(JS)是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。(MDN...

Weex在内涵发现页中的工程实践(weex唯客交易所官网)

React-Native和Weex是目前最为火热的两个客户端跨平台解决方案。从去年2016年9月份开始,IES在抖音产品中应用了ReactNative,中途遇到了很多的问题,尤其是长列表的性能问题一...

新恒汇:公司主要业务包括智能卡业务、蚀刻引线框架业务以及物联网eSIM芯片封测业务

证券日报网讯新恒汇7月3日在互动平台回答投资者提问时表示,公司主要业务包括智能卡业务、蚀刻引线框架业务以及物联网eSIM芯片封测业务。具体请关注公司公告和公开披露信息。(编辑王雪儿)...

“移”科普——什么是物联网?(移动设备物联网物联网应用实例)

物联网(InternetofThings,简称IoT)是指通过互联网将物理世界与数字世界相连接,实现物与物之间的智能互联的网络。它是一种新型的信息通信技术,通过传感器、嵌入式系统、网络技术等手段,...

如何自己搭建一个物联网平台?(自建物联网云平台)

自己搭建一个物联网(IoT)平台需要涉及多个关键步骤,包括硬件设备的选择、软件开发、网络通信、安全性设计以及数据管理。以下是搭建物联网平台的基本流程:1.确定物联网平台架构一个完整的物联网平台通常包...

物联网数据接入篇-应用层 Modbus(5)

前四篇文章讲述的是TCP/IP模型中的网络接口层、网络层、传输层、应用层一,这里到了第四层应用层二。由于协议比较多,就分开篇来介绍。这篇讲Modbus协议,后面再讲MQTT协议、CoAP协议、...

乐鑫ESP32-C5全面量产:行业首款双频Wi-Fi 6的RISC-V SoC

IT之家5月2日消息,乐鑫信息科技4月30日宣布,ESP32-C5现已全面进入量产。ESP32-C5宣称是行业首款2.4&5GHz双频Wi-Fi6的RISC-...

Vue Shop Admin:强大而易用的后台管理系统模板

VueShopAdmin是一个基于Vue.js框架的后台管理系统模板。它具有简洁、易用和美观的特点,非常适合开发人员用于快速构建各种类型的管理系统。这个模板使用了最新的技术,如Vue3、V...

基于Prometheus的自动化巡检(prometheus自动发现详解)

!!大家好,我是乔克,一个爱折腾的运维工程,一个睡觉都被自己丑醒的云原生爱好者。作者:乔克公众号:运维开发故事道路千万条,安全第一条。操作不规范,运维两行泪。前言目前,大部分公司都采用Promet...

取消回复欢迎 发表评论: