阿里淘宝一直在推的响应式编程到底是个什么鬼?

BootStrap响应式项目实战之世界杯网页设计 响应式布局:页面可以随着设备的变化而动态改变。 ​ 淘宝:pc端一套页面:不能随着屏幕的缩小而变化;​ 移动端:另外一套页面,可以随着屏幕的放大、缩小改变(m.taobao.com)阿里公司:财大气粗可以做多套页面。​ 苹果公司:一套页面,随着pc、pad、手机端多端变化而变化。优点:​ 1.适配多端;​ 2.页面简介缺点:​ 1.页面内容要更多,因为要适配不同的设备;​ 2.技术要求更广泛。中文网:https://v3.bootcss.com/[外链图片转存失败, 阅读详情

随着这些年智能手机的发展和普及,我们的服务器端要应对日益增长的巨大流量。

从开发的角度来看,这就要求我们必须设计出高扩展性和高可用性的程序,以确保能够适应日益增长的请求所带来的压力。

而从使用者的角度来看,他们并不会关心后台到底是怎样的,而更关注App界面的易用性和是否美观,最重要的是每次操作能否得到快速的响应。

举一个例子,在CPU还是单核的年代,计算机上只运行一个程序就能够将CPU占用得满满当当。如果计算机上同时运行两个程序,用户就会觉得卡顿,此时CPU要通过上下文切换轮流处理这两个程序,而这个切换过程会消耗CPU资源,以及占用更多的内存资源。而在CPU是多核的时代,我们可以同时打开多个程序,还可以随意切换,并且没有丝毫停滞感。

与硬件端的发展相似,现在Web前端已经可以实现单页应用。举一个例子,在使用音乐App的场景下,点开一个歌单,这个获取歌单的过程可能由于多种原因而产生延时;与此同时,可以切换到这个App的评论区,查看评论将丝毫不影响后台正在进行的获取歌单的任务,等切换回来时可以立马展示获取到的歌单。

于是,对开发人员来说,有两种选择摆在面前。第一种是在从数据库中查找歌单任务完成之前,让用户一直等待,而不能进行其他操作;第二种是用户可以在查找歌单任务执行期间同时使用其他功能,而不是切换回来之后重新查找。

对于用户来说,第二种肯定是最佳选择,至此引出了我们的话题:基于异步的开发模式和传统的基于同步的开发模式。后者比较简单,不必多说,因此我们接下来要介绍的就是基于异步的开发模式,即异步编程模式。

异步编程模式

大家学Java这么久,应该都很清楚入口函数main,异步编程模式意味着在执行main函数的主线程下同时并行且非阻塞地运行一个或多个任务。

这种异步编程模式带给我们的最主要的好处就是,可使程序的性能和响应速度得到大幅提升。这也是我们一直所追求的目标,无论作为开发者还是消费者,我们都不希望一直处于等待、等待、再等待的状态。所以通过异步编程模式,消费者可以在明知道某个任务会消耗很长时间的情况下,通过无障碍地使用其他功能,仍能获得良好的体验。

并发

可以这么说,并发很好地利用了CPU时间片的特性,也就是操作系统在当前时间片内选择并运行一个任务,接着在下一个时间片内选择并运行另一个任务,并把前一个任务设置成等待状态。其实这里想表达的是,并发并不意味着并行。

具体介绍几种情况,分别如下。

  • 有时候多线程执行会提高应用程序的性能,而有时候反而会降低应用程序的性能。这在JDK中Stream API的使用上体现得很明显。如果任务量很小,而我们又使用了并行流,反而降低了性能。
  • 我们在多线程编程中可能会同时开启或者关闭多个线程,这会产生大量的性能开销,也降低了程序性能。
  • 当我们的线程同时都处于等待I/O的过程中时,并发可能会阻塞CPU资源,其造成的后果不仅是用户等待结果,而且会浪费CPU的计算资源。
  • 如果几个线程共享了一个数据,情况就变得有些复杂了,我们需要考虑数据在各个线程中状态的一致性。为了达到这个目的,我们很可能会使用Synchronized或者lock。

现在,你应该对并发有一定的认知了吧。并发确实是一个好东西,但并不一定会实现并行。并行指的是在多个CPU核上同一时间运行多个任务,或者一个任务分为多块执行(如ForkJoin)。在单核CPU上就不要考虑并行了。

补充一点,实际上,多线程就意味着并发,但是并行只发生在将这些线程于同一时间调度分配到不同CPU核上执行的时候。也就是说,并行是并发的一种特定形式。

并行开发初探

现实中,再大的项目落实到细节上其实都是由多人协作完成的,而每个人在做自己的工作的时候只能一步步地做。可以说项目会被分解成一个个模块,由几个部门一同开发,而在每个部门中其又会被分成一个个子任务,由每个人来负责,最后协作汇总。

我们都知道,CPU也是一个接着一个指令地执行任务的。根据上面描述的场景,我们可以做类比,这里所谓的并行开发就是将一个大任务拆成许多部分来同时执行的。这样就更好地利用了多处理器多核环境,而拆分的每个任务都是独立执行的,并且每个任务彼此之间的执行顺序也没什么关系。通过并行执行,大型问题的解决速度直接快了很多,同时也可以更加高效地利用内存。

基于线程模型,我们可以通过良好的控制来实现用户访问功能的流程,但是为了后台服务器能够更好地进行数据的处理,可以根据需要将并发处理设定为一个开关操作。此操作可自动根据任务的数量来分配线程,同时我们需要一套处理数据的模型。从架构层面,我们拿消息中间件来说,消息中间件连接的各个工程作为一个整体就可以看成数据的一种流向处理,客户端通过订阅生产所设定的Topic来做数据的接收处理。而往小的API方向考虑,可以试着理解JDK中流的概念或者Linux命令中管道的概念(只不过管道和流都是基于推的模式),从中抽象出一个更好用的模型,然后将并发处理的开关操作作为其中的一环加入即可。这时,响应式编程(Reactive Programming)就呼之欲出了。

流(Stream)

因为本书后面会多次使用流的概念,所以在此专门介绍一下。在我们平时的编程开发中,往往练就了一番使用Collections框架提供的API熟练、高效地处理数据的能力,对于较复杂的数据,我们往往会用循环来检查。为此,Collections API针对循环遍历的上手难度和方便性做的优化最多,但此优化只适用于从上到下依次执行,并不能高效地利用我们的多核CPU,而通过流则可以很好地解决这个问题。

其实对于流,完全不需要将其想得多么高大上,其就像一条河中的水,有源头,有处理过程,同样有最好的消费归宿。“滚滚长江东逝水”这句歌词恰好道出了流的一次性特性。

通过上面的简单场景,可以总结流的特性如下。

  • 流中的元素是有顺序的。
  • 流需要一个数据源。流可以将集合、数组、文件或者其他的I/O资源作为其输入的数据源。
  • 丰富而流畅的处理操作API。流API提供了与其他函数式语言相同的API(具体API的名字都一样,基本没有什么学习难度),这方便了统一操作,如filter、map、skip、limit等操作。
  • 包含一些隐式操作。比如,针对元素迭代,我们无须手动指定,这是默认实现的。另外,在最终具体消费的时候,才会执行流的整个处理过程。

响应式流(Reactive Stream)

从消息中间件的使用场景可知,在这个数据爆炸的时代,我们的需求在升级,不仅是前台访问后台,取一组数据;而且更多的是面对海量数据,这时需要将其过滤、修改、转换为我们所需要的数据,而处理这些数据需要大量的时间。为了突破这个瓶颈,我们可以使用流来快速处理和响应。也正是基于此,下面来学习一套类似于消息中间件整体使用场景的API,为此需要了解响应式流API的规范和设计思想,以更好地服务业务,而无须苦苦挣扎,使用最基础的流API。

何为消息中间件,从简单的场景理解它就像QQ。比如,我们都加入了QQ群,而作为群中的一员,我们既是消息的生产者,也是消息的消费者。群中的成员想要获取消息,首先要加入这个群,即订阅,于是生产、消费、订阅这几个动作就都产生了。

下面介绍一下响应式流的特性。

异步

前面已经有所介绍,在传统开发模式下,我们是一个方法接着一个方法执行的,最终消耗的时长是这些方法消耗的总时长。而基于异步编程模式,由于这些操作是同时并行执行的,因此最终消耗的时长是这些操作中消耗时间最长的操作所消耗的时长。也就是说,在大量任务需要执行的情况下,异步编程模式为我们的程序带来了快速响应。

背压(Back Pressure)

背压是响应式流的一个规范。比如,上游滔滔江水来,下游河道窄浅,一旦发生洪水,后果将不堪设想,为了减轻下游的压力,索性就建设大坝。回到响应式流,流中的元素会由生产者(Producer)在一端生产出来,而在另一端由消费者(Consumer)消费掉。一旦元素的生产速度超过了消费者的消费速度,就会造成产品的积压,即元素的积压。随着这种积压的不断增加,程序性能就会下降,直至程序“挂掉”。背压(Back Pressure)就是用来解决这个问题的,虽然它可能会增加元素的处理时间,但是它建立起了一个弹性机制,允许程序内部按需调节而不至于使程序崩溃。

具体来说就是,元素由发布者生产、发布,由订阅者或消费者在下游收集。接下来,消费者会根据需求发送一个信号给上游,以此来保证可以将所需元素安全地推送给消费者,而发送信号这个动作是异步进行的。对于订阅者来讲,其可以通过一个拉取策略来发送更多的请求以获取元素。

响应式开发的设计原则

从异步的角度可以知道,我们往往会将一个任务拆分成许多小任务,各个小任务之间可以互不阻塞地异步执行(分而治之),在每一个任务都完成后,将它们的结果进行组合并生成一个结果流。我们通过响应式编程设计即可很轻松地做到这一点。下面介绍一下响应式开发应该遵循的一些设计原则。

响应式系统提供了诸如可响应能力、高可用性、弹性机制、消息驱动和可扩展性等机制,从而确保响应式编程不会使系统资源一直被占用,这样可以使系统的其他组件正常运行。

可响应能力

可响应能力是一个应用程序最重要的功能,在编程的时候我们希望能有一个高效、统一的格式,包括对错误的处理响应,这一点在Web开发过程中已经很常见了。

高可用性

我们的服务器可能会挂掉,无法提供服务。这时可以提供一个备用服务器,这样在主服务器宕机的时候,备用服务器能够顶替上来,达到服务不间断的效果。于是我们看到日常开发中经常会提到各式各样的集群,集群的一个目的就是实现服务不间断。同样,应用程序可能会被拆分为很多系统模块并做成微服务,微服务之间彼此隔离。如果一个微服务挂掉,并不会影响整个系统提供服务,可将损失最小化。

弹性机制

每当有数据到达时,系统会根据需要分配计算资源,以保证数据得到及时处理。响应式系统提供了一个弹性算法机制,当资源需求增长时,分配的计算资源也随之增长;当资源需求减少时,多分配的资源也会随之回收,避免浪费。

消息驱动

简单点讲,消息驱动就是将每个人比作系统中的一个个微服务组件,人与人之间的交流通过消息进行。从这个场景来看,响应式系统通过使用异步的消息在各个组件间交流、通信,这样就可以成功地做到各个组件之间的隔离和松耦合,也就可以更轻松、灵活地扩展和维护系统了。

可扩展性

开发中经常会面对持续不断出现的新需求。可以这样说,我们现在开发的软件无法完全满足未来的需求,不仅可能会因为需要添加新功能而无法满足,而且可能会因为日益增长的访问压力而逐渐无法满足,并且这个压力可能仅仅集中施加在几个模块上。在理解了这些之后,我们要做的不仅是在一个项目中添加代码,而且还要在不影响旧代码的前提下,对这个项目进行扩展。部分功能模块可以进行水平扩展(集群化),也可以单独开发微服务进行云平台挂载(即功能性的垂直扩展),而路由和相关的其他模块只需要修改极少的代码。

响应式开发的好处

响应式开发的好处主要包含以下几点。

  • 提高所开发程序的性能。
  • 在多核机器上,提高了计算资源的利用率。
  • 为异步编程提供了一个更靠谱的可维护方案。
  • 提供了背压机制,也就是对计算资源提供了过载保护功能。

响应式开发工具库

已经有很多工具库实现了响应式流的标准,包括Akka、Reactor、RxJava、Streams、Vert.x等。下面简单介绍几种,在后面的章节中我会重点讲解RxJava(关于Reactor,会在本系列丛书的另一本书中具体讲解)。

RxJava简介

通过官方GitHub可知,RxJava是使用Java语言开发的专门针对JVM的一种响应式扩展工具,通过它可以轻松地在服务器端实现并发操作。RxJava的目的就是处理客户端越来越复杂的请求,在服务器端通过并行计算快速地响应请求。

接下来,我们开始了解RxJava到底是怎么一回事,作为数据的消费者,我们会对获得的数据做出各种反应。有句话说得好,“跳出三界外,不在五行中”,在我们以旁观者的视角来看这件事的时候,其实它就是一个观察者模式的实际体现。RxJava下的响应式编程其实就是基于影院里的电影(Observable)提供的内容(生产者数据)传播给订阅者,然后订阅者做出相应的反应。

结合上面的场景,下面对RxJava所涉及的要点进行解释。

  • Observable:表示数据源,Observable会发出一定数量的元素,发送可能会成功,也可能在这个过程中出现状况而失败。从电影院的场景可以知道,同一时间Observable可以有多个订阅者。
  • Observer或Subscriber:表示订阅者,通过监听Observable来消费Observable所发送的元素。
  • Methods:表示一系列操作API,对下发数据进行加工整合。
  • onNext:在一个元素被Observable发送出去的时候,通过该方法可以调用每一个订阅者。
  • onComplete:在Observable成功发送完所有数据后,会调用这个方法来收尾。
  • onError:当Observable发送数据的过程中出现错误的状况时,会调用这个方法结束发送并返回一个error事件。
  • RxJava所带来的好处主要如下。
  • 允许我们进行一系列的异步操作。
  • 有时为了跟踪状态,我们会通过一个原子类变量保存之前计算的值。我们无须专门使用原子类来跟踪状态,因为RxJava中已经封装了这些操作。
  • RxJava提供了一个在整个执行过程中发生错误时的处理途径。

Reactor简介

Spring 5官方文档提到,其通过Reactor的支持,在服务器端获得了更高的性能和更快的响应速度。SpringWebFlux作为新一代的Web开发框架,以Reactor作为基础框架进行异步编程的开发,从而可以使我们写出性能更好的Web应用程序。如果大家看过我博客中关于Spring 5源码分析的系列文章,就可以知道Spring MVC框架的整个运行过程其实使用了事件驱动(Event-Driven)模式,而Reactor自身的设计也使用了这个模式。参考前面的电影院场景,当电影的画面和声音传到你的眼睛和耳朵中时,会引发你喜怒哀乐的情绪反应。再形象一点,在拳击选手一个直拳要打到对方选手脸上的时候,对方选手会躲闪。电影的画面和拳击选手的直拳动作都是一种事件的表现,根据事件做出相应处理的整个过程就是所谓的事件驱动。在Spring里,这就相当于我们的后台服务器接收事件请求,通过multicaster多路分发器来分发给相应的监听器(Listener),最后由监听器里定义的相应的handler来做具体处理。整个过程大概就是这样的。

知道了上面的这些内容,通过使用Reactor,我们写出的程序就可以按照事件驱动的模式很轻易地异步运行了。

1.Reactor的优点

Reactor支持完全无阻塞,其主要的目标之一就是解决传统Web开发方案对于异步支持的各种弊病。它提供了十分有效的途径来支持背压。它还有以下优点。

  • 丰富的API,可以对数据流进行操作。
  • 提供了一种可读性更强的代码书写方式,使我们所写的代码可以更方便地得到维护。
  • 与流相同,无消费,不执行。
  • 消费者具备发信号通知生产者元素按需下发的能力(RxJava同样具备)。

2.Reactor的核心功能

Reactor项目的主要模块是reactor-core,这是一个专门用于支持响应式流规范的类库,其支持Java 8及后续版本。通过查看Reactor API,可知它和RxJava很像。Reactor3是Reactor 2和RxJava的核心贡献开发者一起完成的一个混合版本,这也是本章把这几个东西放在一起介绍,然后分章讲解的很重要的原因,因为这样更易于理解。

Reactor与RxJava有相同的Publisher、Subscriber、Subscription和Processor核心接口。这里只简单介绍Publisher最常用的两个实现Mono和Flux,以及相关的操作符。

  • Mono:表示一个特殊的Publisher,它可以发送0个或1个元素。
  • Flux:表示一个特殊的Publisher,它可以发送0到n个元素。
  • 操作符:元素在从Publisher发送给订阅者之前,可能会需要进行一些处理,包括转换、过滤操作等。

MongoDB简介

在后面的实战开发中,我们可能会用到MongoDB,官方提供的MongoDBReactive Streams Java版本的驱动包API可以对MongoDB进行异步流处理,而且是无阻塞支持背压的。这里只是提一下,说明我们的数据库操作层面也开始做到了对响应式流API标准的支持。

响应式项目用例

前面说了那么多,大家可能依然有点不明白,那么为了更好地理解响应式系统(Reactive System),我们看看它与传统项目的不同之处。

以我们生活中的股票场景为例,我们需要看到股票信息的实时动态展示。这时我们会打开并保持一个页面,这个页面可以实时显示股票信息。开发人员需要做的是,将最新的数据更新到这个股票展示页面上。作为股民,面对的是“差之毫厘,失之千里”的局面。对他们来说,数据刷新得越及时,对决策越有利(在这里,我们只从响应式的角度来考虑这个问题,现实项目中会有基于WebSocket的实现,Spring MVC中也有SSE的实现)。

传统开发模式

根据以往的开发经验,我们会主动地检查股票价格有没有变化,如果有变化,就从后台拉取最新的数据。如图1-1所示的流程图就代表着传统开发模式。

在传统开发模式下,一旦开始渲染访问页面,就会每隔一段时间(图1-1中是1分钟)发送AJAX请求到后台的查询服务去请求股票价格数据。使用这种方式,无论股票价格是否真的发生变化,都会去请求,但无法保证股票价格的变化会被立刻传递到Web页面上。

响应式开发模式

响应式开发模式通过事件驱动的方式将各个组件连接到一起,以实现在事件发生时其他组件可以立即进行响应。

也就是说,在加载股票价格页面后,这个页面会有一个专属ID注册到股票查询服务上。一旦使股票价格发生变化的事件产生,这个事件(Event)就会触发响应,最新的股票价格就会在Web页面上进行更新显示。如图1-2所示说明了整个流程。

可以看到,响应式开发模式一般包括下面3个步骤。

(1)订阅(Subscribing)事件。

(2)事件的发生与传播。

(3)解除订阅。

在股票价格页面初始化加载的时候,其中有一个动作就是订阅当前使股票价格发生变化的事件源,可以认为事件源是消息中间件里的主题(Topic)(或者是我们订阅的一个RSS主题),而不同的响应式框架会有不同的具体方式,使用消息中间件也可以实现订阅。

在我们所关注的某只股票价格发生变化的时候,一个新的事件就会产生并分发给这个事件的订阅者。我们的Web页面会及时地接收并更新股票价格数据。而一旦Web页面关闭或者刷新,一个解除订阅的请求就会被发送至后台。

传统开发模式和响应式开发模式的比较

可以看到,传统开发模式是比较简单的,而响应式开发模式需要我们实现一个订阅和事件传播链。如果事件的传播需要跨项目,也就是涉及其他项目,那么就可能会使用到消息中间件,这将会变得复杂,其并不属于本书的范围,此处不做讨论。

在传统开发模式中,更新股票价格页面主要是基于盲目的主动拉取来实现的,前端根本就不知道会不会有数据发生变化。这也就意味着无论后台数据有没有发生变化,前端都需要定时从后台拉取一次数据。而在响应式开发模式中,一旦注册订阅了价格变动事件,那么只有这只股票的价格发生变化才会触发一系列的操作,这样明显提高了程序性能和用户体验。

在传统开发模式中,这个例子中线程的生命周期会比较长,这也就意味着该线程所使用的资源在这个过程中会被线程锁定。考虑到同一时刻服务器会接收大量的请求,这样势必会造成更多的线程相互争夺资源。在响应式开发模式中,线程生存的时间短,这也就意味着争夺资源的情况较少。

YOLOv8【第十章:多任务扩展深度篇·第19节】YOLOv8 与 DeepLabV3+ 对比——实时性与精度的权衡! 🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。 阅读详情

相关推荐

✨从零搭建 Ubuntu22.04 + Python3.11 + PyTorch2.5.1 GPU Docker 镜像并上传 Docker Hub

构建一个带 GPU 支持的深度学习开发镜像;使用 PyTorch 2.5.1(CUDA 12.4)环境;发布并托管 Docker 镜像至 Docker Hub;验证 GPU 环境正常运行!🎉 这将极大提升你的项目部署效率,尤其是在多人协作或跨平台部署场景中。

用大模型重构生活:猫奴程序员的AI智能日常记录 1578

全面异步化:淘宝反应式架构升级探索

2018 年初,淘宝开始尝试进行整个架构升级(代号Tango:Taobao Architecture Next GeneratiOn),经过近一年的探索,实现了全面异步化...

淘系技术 567

三维变换矩阵实战——三维点云的旋转、缩放、镜像、错切、平移、正交投影

旋转矩阵:右边矩阵是点云的原始坐标,左边的是旋转矩阵可视化:绕x轴旋转90度。

weixin_43850909的博客 8229

阿里内部推出Spring响应式微服务,真的很香

当下互联网行业飞速发展,快速的业务更新和产品迭代也给系统开发过程和模式带来新的挑战。在这个时代背景下,以Spring Cloud为代表的微服务架构实现技术应运而生。微服务架构是一种分布式系统,在业务、技术和组织等方面具备相应优势的同时,也不得不面临分布式系统所固有的问题。确保微服务系统的即时响应性和服务弹性是我们构建微服务架构的一大挑战。幸运的是,Spring框架的开发人员已经创建了一个崭新的、支持响应式的项目版本,用来支持响应式微服务架构的设计和开发。

公众号:该用户快成仙了 167

二阶锥松弛在配电网最优潮流计算中的应用(IEEE33节点配电网最优潮流算例matlab程序)(yalmip+cplex)

文献[7]建立了以支路潮流计算为基础的OPF模型,针对OPF中的非凸性约束,采用SOCR技术将其松弛为二阶锥约束,整个 OPF 模型则被转化为二阶锥规划( Second Order Cone Programming,SOCP)问题,对其求解可以得到全局最优解。其次结合辐射型配电网潮流特点建立支路潮流约束,并考虑配电网中的可控单元,包括分布式电源和离散、连续无功补偿装置,建立其出力约束,该模型为非凸非线性模型;式中,αj,t和βij,t分别为t时段内节点i电压的二次方和支路ij电流的二次方。

weixin_47365903的博客 1万+

Android无线调试:adb tcpip连接实战指南

本文详细介绍了Android无线调试的完整流程,重点讲解如何使用adb tcpip命令通过Wi-Fi连接设备,摆脱数据线束缚。涵盖环境配置、连接实战、稳定性优化及常见问题排查,帮助开发者高效实现无线adb调试,提升工作效率。

pink的博客 722

响应式编程介绍

我之前替换过这些组件,且不说替换之后的很多隐藏的问题,就查询处理性能效果来说,并没有发生多大的改变,后来我才明白,就像刚开始提的,一个响应式的系统要求系统中各个部分都需要响应式的提供服务,而不是某个组件,一条响应式链路中某个节点如果只能同步阻塞,那么这条链路他就不是响应式的,由此带来的问题就是改造一个现有的系统为响应式,那将是一个巨大的灾难。最为关注的 jdbc 也有对应的支持了,r2dbc.io/ (Reactive 本来不支持 JDBC,最根本的原因是,JDBC 不是 non-blocking 设计)

老男孩的架构路 3060

从AP到ADSP:高通8650 AudioReach中GSL-Passthru-GPR的数据通路剖析

本文深入剖析了高通骁龙8650平台AudioReach架构中,音频数据从应用处理器(AP)到音频数字信号处理器(ADSP)的完整传输路径。重点解析了GSL(Graph Service Layer)如何封装命令,并通过Passthru驱动与GPR(Generic Packet Router)协同工作,实现跨处理器的高效、异步数据交换,揭示了现代手机复杂音频系统背后的核心通信机制。

cherry的博客 536

不要迷信响应式编程,它只是编程范式中的“小丑”

我不是很理解,为什么越来越多的项目打着高性能的旗号,迷信般的使用响应式编程框架,然后把代码搞的乱七八糟。响应式编程真的那么香么?还是“天下苦响应式编程久已”,在迫害我们的祖国花朵?。在我看来,响应式编程至少犯了三宗罪:1. 易造成复杂;2. 调试困难;3. 性能迷雾。 鉴于此,我希望开发同学们在选择编程范式的时候,能擦亮自己的眼睛,选一个真正适合自己和团队的编程范式。罪一、易造成复杂响应式编程的代...

我的新书《代码精进之路:从码农到工匠》 7944

YOLOv11【第六章:模型压缩与极致优化篇·第15节】YOLOv11 专用剪枝工具库使用指南!

🏆 本文收录于专栏 《YOLOv11实战:从入门到深度优化》。本专栏围绕 YOLOv11 的改进、训练、部署与工程优化 展开,系统梳理并复现当前主流的 YOLOv11 实战案例与优化方案,内容目前已覆盖 分类、检测、分割、追踪、关键点、OBB 检测 等多个方向。

**My Coding Family** 1312

FFmpeg 开发(01):FFmpeg 编译和集成

尽管 FFmpeg 功能强大,但是由于其采用的是带有传染性的 LGPL/GPL 开源协议,所以一些大厂基本上都是自己独立开发类似的音视频处理库,甚至在接口和组织模块上模仿 FFmpeg 。

字节流动 1万+

Spring 响应式编程,真香!!!

异步非阻塞的福音~

riemann_的博客 2655

YOLO11改进-注意力-引入自调制特征聚合模块SMFA

SMFA(自调制特征聚合模块): SMFA模块用于协同建模局部和非局部信息,它分为两个分支:一个是EASA(Efficient Approximation of Self-Attention,简化的自注意力分支),用于捕获非局部信息;另一个是LDE(Local Detail Estimation,局部细节估计分支),用于捕获局部细节。EASA通过对输入特征进行下采样,然后利用全局特征的方差进行调制,再与原始特征进行聚合,提取非局部结构信息。LDE分支则通过卷积操作提取输入特征中的高频局部信息。

qq_64693987的博客 2208

Reactive Practice at Taobao 开源项目教程

Reactive Practice at Taobao 开源项目教程 1. 项目介绍 Reactive Practice at Taobao 是一个开源项目,旨在演示和练习响应式编程的概念和应用。该项目基于阿里巴巴开源的响应式编程框架,目的是帮助开发者理解和掌握响应式编程的核心思想,以及如何在实际项目中应用这些思想。 2. 项目快速启动 环境准备 JDK 1.8 或更高版本 Maven 3.3....

gitblog_00604的博客 657

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【淘宝flexible】阿里 响应式 h5 手机端 自适应 页面

【淘宝flexible】<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script> (function flexible (window, document) { var docEl = document.do...

aiqingshan6402的博客 687

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

阿里专家杜万:Java响应式编程,一文全面解读

本篇文章来自于2018年12月22日举办的《阿里云栖开发者沙龙—Java技术专场》,杜万专家是该专场第四位演讲的嘉宾,本篇文章是根据杜万专家在《阿里云栖开发者沙龙—Java技术专场》的演讲视频以及PPT整理而成。 摘要:响应式宣言如何解读,Java中如何进行响应式编程,Reactor Streams又该如何使用?热衷于整合框架与开发工具...

weixin_34292959的博客 103

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

最新仿淘宝源码使用原生HTML+CSS描写

今天给大家分享前不久写的一个淘宝网静态页面 源码下载地址: 下面提供html和css样式代码 <!DOCTYPE html> <html> <head> <!-->资源来自崔俊杰博客qq:1746272020<--> <title>淘宝网-淘!我喜欢</title> <meta charset="utf-8"> <link rel="shortcut icon" href="logo.png" ty

小崔同学 1万+

livedatabus详解,阿里是如何用他来做淘宝架构的?

Database。

ainingmeng的博客 1214

livedatabus详解,阿里是如何用他来做淘宝架构的?(1)

对程序员来说,很多技术的学习都是“防御性”的。也就是说,我们是在为未来学习。我们学习新技术的目的,或是为了在新项目中应用,或仅仅是为了将来的面试。但不管怎样,一定不能“止步不前”,不能荒废掉。!文章以下内容会给出阿里与美团的面试题(答案+解析)、面试题库、Java核心知识点梳理等[外链图片转存中…(img-jkul3wgV-1711937623165)][外链图片转存中…(img-OFkPe7N5-1711937623166)]

m0_57540655的博客 856

2015阿里实习生内推面经

一面(杭州的电话)2015/3/6,1:54 - 2:15,20分钟,中间断线两次先自我介绍。汇惠APP有哪些功能?…你负责什么?底部导航栏用什么实现的?RadioGroup,主页面的子页面用什么实现的?TabActivity“优惠”页面布局是怎么组织的?下拉刷新是怎么做的,自己写的还是第三方的?ListView用的是系统的还是自己写的?系统的是如何优化的?你用到什么优化的方法?ViewHolde

DC的陋室 4866
上一篇: 什么,分布式缓存搞崩了注册中心?
下一篇: Redis 如何做持久化与恢复?
JavaMonsterr
博客等级 码龄4年 211粉丝 481原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值