作者:じ☆ve宝贝
当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题。为了解决这些性能压力带来问题,我们需要在Web系统架构层面搭建多个层次的缓存机制。在不同的压力阶段,我们会遇到不同的问题,通过搭建不同的服务和架构来解决。 ##Web负载均衡 Web负载均衡(Load Balancing),简单地说就是给我们的服务器集群分配“工作任务”,而采用恰当的分配方式,对于保护处于后端的Web服务器来说,非常重要。  载均衡的策略有很多,我们从简单的讲起哈。 ####1. HTTP重定向 当用户发来请求的时候,Web服务器通过修改HTTP响应头中的Location标记来返回一个新的url,然后浏览器再继续请求这个新url,实际上就是页面重定向。通过重定向,来达到“负载均衡”的目标。例如,我们在下载PHP源码包的时候,点击下载链接时,为了解决不同国家和地域下载速度的问题,它会返回一个离我们近的下载地址。重定向的HTTP返回码是302,如下图:  如果使用PHP代码来实现这个功能,方式如下:  这个重定向非常容易实现,并且可以自定义各种策略。但是,它在大规模访问量下,性能不佳。而且,给用户的体验也不好,实际请求发生重定向,增加了网络延时。 ####2. 反向代理负载均衡 反向代理服务的核心工作主要是转发HTTP请求,扮演了浏览器端和后台Web服务器中转的角色。因为它工作在HTTP层(应用层),也就是网络七层结构中的第七层,因此也被称为“七层负载均衡”。可以做反向代理的软件很多,比较常见的一种是Nginx。  Nginx是一种非常灵活的反向代理软件,可以自由定制化转发策略,分配服务器流量的权重等。反向代理中,常见的一个问题,就是Web服务器存储的session数据,因为一般负载均衡的策略都是随机分配请求的。同一个登录用户的请求,无法保证一定分配到相同的Web机器上,会导致无法找到session的问题。 解决方案主要有两种: 1.配置反向代理的转发规则,让同一个用户的请求一定落到同一台机器上(通过分析cookie),复杂的转发规则将会消耗更多的CPU,也增加了代理服务器的负担。 2.将session这类的信息,专门用某个独立服务来存储,例如redis/memchache,这个方案是比较推荐的。 反向代理服务,也是可以开启缓存的,如果开启了,会增加反向代理的负担,需要谨慎使用。这种负载均衡策略实现和部署非常简单,而且性能表现也比较好。但是,它有“单点故障”的问题,如果挂了,会带来很多的麻烦。而且,到了后期Web服务器继续增加,它本身可能成为系统的瓶颈。 ####3. IP负载均衡 IP负载均衡服务是工作在网络层(修改IP)和传输层(修改端口,第四层),比起工作在应用层(第七层)性能要高出非常多。原理是,他是对IP层的数据包的IP地址和端口信息进行修改,达到负载均衡的目的。这种方式,也被称为“四层负载均衡”。常见的负载均衡方式,是LVS(Linux Virtual Server,Linux虚拟服务),通过IPVS(IP Virtual Server,IP虚拟服务)来实现。  在负载均衡服务器收到客户端的IP包的时候,会修改IP包的目标IP地址或端口,然后原封不动地投递到内部网络中,数据包会流入到实际Web服务器。实际服务器处理完成后,又会将数据包投递回给负载均衡服务器,它再修改目标IP地址为用户IP地址,最终回到客户端。  上述的方式叫LVS-NAT,除此之外,还有LVS-RD(直接路由),LVS-TUN(IP隧道),三者之间都属于LVS的方式,但是有一定的区别,篇幅问题,不赘叙。 IP负载均衡的性能要高出Nginx的反向代理很多,它只处理到传输层为止的数据包,并不做进一步的组包,然后直接转发给实际服务器。不过,它的配置和搭建比较复杂。 ####4. DNS负载均衡 DNS(Domain Name System)负责域名解析的服务,域名url实际上是服务器的别名,实际映射是一个IP地址,解析过程,就是DNS完成域名到IP的映射。而一个域名是可以配置成对应多个IP的。因此,DNS也就可以作为负载均衡服务。  这种负载均衡策略,配置简单,性能极佳。但是,不能自由定义规则,而且,变更被映射的IP或者机器故障时很麻烦,还存在DNS生效延迟的问题。 ####5. DNS/GSLB负载均衡 我们常用的CDN(Content Delivery Network,内容分发网络)实现方式,其实就是在同一个域名映射为多IP的基础上更进一步,通过GSLB(Global Server Load Balance,全局负载均衡)按照指定规则映射域名的IP。一般情况下都是按照地理位置,将离用户近的IP返回给用户,减少网络传输中的路由节点之间的跳跃消耗。  CDN在Web系统中,一般情况下是用来解决大小较大的静态资源(html/Js/Css/图片等)的加载问题,让这些比较依赖网络下载的内容,尽可能离用户更近,提升用户体验。 例如,我访问了一张imgcache.gtimg.cn上的图片(腾讯的自建CDN,不使用qq.com域名的原因是防止http请求的时候,带上了多余的cookie信息),我获得的IP是183.60.217.90。  这种方式,和前面的DNS负载均衡一样,不仅性能极佳,而且支持配置多种策略。但是,搭建和维护成本非常高。互联网一线公司,会自建CDN服务,中小型公司一般使用第三方提供的CDN。 ##Web系统的缓存机制的建立和优化 刚刚我们讲完了Web系统的外部网络环境,现在我们开始关注我们Web系统自身的性能问题。我们的Web站点随着访问量的上升,会遇到很多的挑战,解决这些问题不仅仅是扩容机器这么简单,建立和使用合适的缓存机制才是根本。 最开始,我们的Web系统架构可能是这样的,每个环节,都可能只有1台机器。  我们从最根本的数据存储开始看哈。 ##一、 MySQL数据库内部缓存使用 MySQL的缓存机制,就从先从MySQL内部开始,下面的内容将以最常见的InnoDB存储引擎为主。 ####1. 建立恰当的索引 最简单的是建立索引,索引在表数据比较大的时候,起到快速检索数据的作用,但是成本也是有的。首先,占用了一定的磁盘空间,其中组合索引最突出,使用需要谨慎,它产生的索引甚至会比源数据更大。其次,建立索引之后的数据insert/update/delete等操作,因为需要更新原来的索引,耗时会增加。当然,实际上我们的系统从总体来说,是以select查询操作居多,因此,索引的使用仍然对系统性能有大幅提升的作用。 ####2. 数据库连接线程池缓存 如果,每一个数据库操作请求都需要创建和销毁连接的话,对数据库来说,无疑也是一种巨大的开销。为了减少这类型的开销,可以在MySQL中配置thread_cache_size来表示保留多少线程用于复用。线程不够的时候,再创建,空闲过多的时候,则销毁。  其实,还有更为激进一点的做法,使用pconnect(数据库长连接),线程一旦创建在很长时间内都保持着。但是,在访问量比较大,机器比较多的情况下,这种用法很可能会导致“数据库连接数耗尽”,因为建立连接并不回收,最终达到数据库的max_connections(最大连接数)。因此,长连接的用法通常需要在CGI和MySQL之间实现一个“连接池”服务,控制CGI机器“盲目”创建连接数。  建立数据库连接池服务,有很多实现的方式,PHP的话,我推荐使用swoole(PHP的一个网络通讯拓展)来实现。 ####3. Innodb缓存设置(innodb_buffer_pool_size) innodb_buffer_pool_size这是个用来保存索引和数据的内存缓存区,如果机器是MySQL独占的机器,一般推荐为机器物理内存的80%。在取表数据的场景中,它可以减少磁盘IO。一般来说,这个值设置越大,cache命中率会越高。 ####4. 分库/分表/分区。 MySQL数据库表一般承受数据量在百万级别,再往上增长,各项性能将会出现大幅度下降,因此,当我们预见数据量会超过这个量级的时候,建议进行分库/分表/分区等操作。最好的做法,是服务在搭建之初就设计为分库分表的存储模式,从根本上杜绝中后期的风险。不过,会牺牲一些便利性,例如列表式的查询,同时,也增加了维护的复杂度。不过,到了数据量千万级别或者以上的时候,我们会发现,它们都是值得的。 ##二、 MySQL数据库多台服务搭建 1台MySQL机器,实际上是高风险的单点,因为如果它挂了,我们Web服务就不可用了。而且,随着Web系统访问量继续增加,终于有一天,我们发现1台MySQL服务器无法支撑下去,我们开始需要使用更多的MySQL机器。当引入多台MySQL机器的时候,很多新的问题又将产生。 ####1. 建立MySQL主从,从库作为备份 这种做法纯粹为了解决“单点故障”的问题,在主库出故障的时候,切换到从库。不过,这种做法实际上有点浪费资源,因为从库实际上被闲着了。  ####2. MySQL读写分离,主库写,从库读。 两台数据库做读写分离,主库负责写入类的操作,从库负责读的操作。并且,如果主库发生故障,仍然不影响读的操作,同时也可以将全部读写都临时切换到从库中(需要注意流量,可能会因为流量过大,把从库也拖垮)。  ####3. 主主互备。 两台MySQL之间互为彼此的从库,同时又是主库。这种方案,既做到了访问量的压力分流,同时也解决了“单点故障”问题。任何一台故障,都还有另外一套可供使用的服务。  不过,这种方案,只能用在两台机器的场景。如果业务拓展还是很快的话,可以选择将业务分离,建立多个主主互备。 ##三、 MySQL数据库机器之间的数据同步 每当我们解决一个问题,新的问题必然诞生在旧的解决方案上。当我们有多台MySQL,在业务高峰期,很可能出现两个库之间的数据有延迟的场景。并且,网络和机器负载等,也会影响数据同步的延迟。我们曾经遇到过,在日访问量接近1亿的特殊场景下,出现,从库数据需要很多天才能同步追上主库的数据。这种场景下,从库基本失去效用了。 于是,解决同步问题,就是我们下一步需要关注的点。 ####1. MySQL自带多线程同步 MySQL5.6开始支持主库和从库数据同步,走多线程。但是,限制也是比较明显的,只能以库为单位。MySQL数据同步是通过binlog日志,主库写入到binlog日志的操作,是具有顺序的,尤其当SQL操作中含有对于表结构的修改等操作,对于后续的SQL语句操作是有影响的。因此,从库同步数据,必须走单进程。 ####2. 自己实现解析binlog,多线程写入。 以数据库的表为单位,解析binlog多张表同时做数据同步。这样做的话,的确能够加快数据同步的效率,但是,如果表和表之间存在结构关系或者数据依赖的话,则同样存在写入顺序的问题。这种方式,可用于一些比较稳定并且相对独立的数据表。  国内一线互联网公司,大部分都是通过这种方式,来加快数据同步效率。还有更为激进的做法,是直接解析binlog,忽略以表为单位,直接写入。但是这种做法,实现复杂,使用范围就更受到限制,只能用于一些场景特殊的数据库中(没有表结构变更,表和表之间没有数据依赖等特殊表)。 ##四、 在Web服务器和数据库之间建立缓存 实际上,解决大访问量的问题,不能仅仅着眼于数据库层面。根据“二八定律”,80%的请求只关注在20%的热点数据上。因此,我们应该建立Web服务器和数据库之间的缓存机制。这种机制,可以用磁盘作为缓存,也可以用内存缓存的方式。通过它们,将大部分的热点数据查询,阻挡在数据库之前。  ####1. 页面静态化 用户访问网站的某个页面,页面上的大部分内容在很长一段时间内,可能都是没有变化的。例如一篇新闻报道,一旦发布几乎是不会修改内容的。这样的话,通过CGI生成的静态html页面缓存到Web服务器的磁盘本地。除了第一次,是通过动态CGI查询数据库获取之外,之后都直接将本地磁盘文件返回给用户。  在Web系统规模比较小的时候,这种做法看似完美。但是,一旦Web系统规模变大,例如当我有100台的Web服务器的时候。那样这些磁盘文件,将会有100份,这个是资源浪费,也不好维护。这个时候有人会想,可以集中一台服务器存起来,呵呵,不如看看下面一种缓存方式吧,它就是这样做的。 ####2. 单台内存缓存 通过页面静态化的例子中,我们可以知道将“缓存”搭建在Web机器本机是不好维护的,会带来更多问题(实际上,通过PHP的apc拓展,可通过Key/value操作Web服务器的本机内存)。因此,我们选择搭建的内存缓存服务,也必须是一个独立的服务。 内存缓存的选择,主要有redis/memcache。从性能上说,两者差别不大,从功能丰富程度上说,Redis更胜一筹。  ####3. 内存缓存集群 当我们搭建单台内存缓存完毕,我们又会面临单点故障的问题,因此,我们必须将它变成一个集群。简单的做法,是给他增加一个slave作为备份机器。但是,如果请求量真的很多,我们发现cache命中率不高,需要更多的机器内存呢?因此,我们更建议将它配置成一个集群。例如,类似redis cluster。 Redis cluster集群内的Redis互为多组主从,同时每个节点都可以接受请求,在拓展集群的时候比较方便。客户端可以向任意一个节点发送请求,如果是它的“负责”的内容,则直接返回内容。否则,查找实际负责Redis节点,然后将地址告知客户端,客户端重新请求。  对于使用缓存服务的客户端来说,这一切是透明的。  内存缓存服务在切换的时候,是有一定风险的。从A集群切换到B集群的过程中,必须保证B集群提前做好“预热”(B集群的内存中的热点数据,应该尽量与A集群相同,否则,切换的一瞬间大量请求内容,在B集群的内存缓存中查找不到,流量直接冲击后端的数据库服务,很可能导致数据库宕机)。 ####4. 减少数据库“写” 上面的机制,都实现减少数据库的“读”的操作,但是,写的操作也是一个大的压力。写的操作,虽然无法减少,但是可以通过合并请求,来起到减轻压力的效果。这个时候,我们就需要在内存缓存集群和数据库集群之间,建立一个修改同步机制。 先将修改请求生效在cache中,让外界查询显示正常,然后将这些sql修改放入到一个队列中存储起来,队列满或者每隔一段时间,合并为一个请求到数据库中更新数据库。  除了上述通过改变系统架构的方式提升写的性能外,MySQL本身也可以通过配置参数innodb_flush_log_at_trx_commit来调整写入磁盘的策略。如果机器成本允许,从硬件层面解决问题,可以选择老一点的RAID(Redundant Arrays of independent Disks,磁盘列阵)或者比较新的SSD(Solid State Drives,固态硬盘)。 ####5. NoSQL存储 不管数据库的读还是写,当流量再进一步上涨,终会达到“人力有穷时”的场景。继续加机器的成本比较高,并且不一定可以真正解决问题的时候。这个时候,部分核心数据,就可以考虑使用NoSQL的数据库。NoSQL存储,大部分都是采用key-value的方式,这里比较推荐使用上面介绍过Redis,Redis本身是一个内存cache,同时也可以当做一个存储来使用,让它直接将数据落地到磁盘。 这样的话,我们就将数据库中某些被频繁读写的数据,分离出来,放在我们新搭建的Redis存储集群中,又进一步减轻原来MySQL数据库的压力,同时因为Redis本身是个内存级别的Cache,读写的性能都会大幅度提升。  国内一线互联网公司,架构上采用的解决方案很多是类似于上述方案,不过,使用的cache服务却不一定是Redis,他们会有更丰富的其他选择,甚至根据自身业务特点开发出自己的NoSQL服务。 ####6. 空节点查询问题 当我们搭建完前面所说的全部服务,认为Web系统已经很强的时候。我们还是那句话,新的问题还是会来的。空节点查询,是指那些数据库中根本不存在的数据请求。例如,我请求查询一个不存在人员信息,系统会从各级缓存逐级查找,最后查到到数据库本身,然后才得出查找不到的结论,返回给前端。因为各级cache对它无效,这个请求是非常消耗系统资源的,而如果大量的空节点查询,是可以冲击到系统服务的。  在我曾经的工作经历中,曾深受其害。因此,为了维护Web系统的稳定性,设计适当的空节点过滤机制,非常有必要。 我们当时采用的方式,就是设计一张简单的记录映射表。将存在的记录存储起来,放入到一台内存cache中,这样的话,如果还有空节点查询,则在缓存这一层就被阻挡了。  #异地部署(地理分布式) 完成了上述架构建设之后,我们的系统是否就已经足够强大了呢?答案当然是否定的哈,优化是无极限的。Web系统虽然表面上看,似乎比较强大了,但是给予用户的体验却不一定是最好的。因为东北的同学,访问深圳的一个网站服务,他还是会感到一些网络距离上的慢。这个时候,我们就需要做异地部署,让Web系统离用户更近。 ##一、 核心集中与节点分散 有玩过大型网游的同学都会知道,网游是有很多个区的,一般都是按照地域来分,例如广东专区,北京专区。如果一个在广东的玩家,去北京专区玩,那么他会感觉明显比在广东专区卡。实际上,这些大区的名称就已经说明了,它的服务器所在地,所以,广东的玩家去连接地处北京的服务器,网络当然会比较慢。 当一个系统和服务足够大的时候,就必须开始考虑异地部署的问题了。让你的服务,尽可能离用户更近。我们前面已经提到了Web的静态资源,可以存放在CDN上,然后通过DNS/GSLB的方式,让静态资源的分散“全国各地”。但是,CDN只解决的静态资源的问题,没有解决后端庞大的系统服务还只集中在某个固定城市的问题。 这个时候,异地部署就开始了。异地部署一般遵循:核心集中,节点分散。 核心集中:实际部署过程中,总有一部分的数据和服务存在不可部署多套,或者部署多套成本巨大。而对于这些服务和数据,就仍然维持一套,而部署地点选择一个地域比较中心的地方,通过网络内部专线来和各个节点通讯。 节点分散:将一些服务部署为多套,分布在各个城市节点,让用户请求尽可能选择近的节点访问服务。 例如,我们选择在上海部署为核心节点,北京,深圳,武汉,上海为分散节点(上海自己本身也是一个分散节点)。我们的服务架构如图:  需要补充一下的是,上图中上海节点和核心节点是同处于一个机房的,其他分散节点各自独立机房。 国内有很多大型网游,都是大致遵循上述架构。它们会把数据量不大的用户核心账号等放在核心节点,而大部分的网游数据,例如装备、任务等数据和服务放在地区节点里。当然,核心节点和地域节点之间,也有缓存机制。 ##二、 节点容灾和过载保护 节点容灾是指,某个节点如果发生故障时,我们需要建立一个机制去保证服务仍然可用。毫无疑问,这里比较常见的容灾方式,是切换到附近城市节点。假如系统的天津节点发生故障,那么我们就将网络流量切换到附近的北京节点上。考虑到负载均衡,可能需要同时将流量切换到附近的几个地域节点。另一方面,核心节点自身也是需要自己做好容灾和备份的,核心节点一旦故障,就会影响全国服务。 过载保护,指的是一个节点已经达到最大容量,无法继续接接受更多请求了,系统必须有一个保护的机制。一个服务已经满负载,还继续接受新的请求,结果很可能就是宕机,影响整个节点的服务,为了至少保障大部分用户的正常使用,过载保护是必要的。 解决过载保护,一般2个方向: 拒绝服务,检测到满负载之后,就不再接受新的连接请求。例如网游登入中的排队。 分流到其他节点。这种的话,系统实现更为复杂,又涉及到负载均衡的问题。 ##小结 Web系统会随着访问规模的增长,渐渐地从1台服务器可以满足需求,一直成长为“庞然大物”的大集群。而这个Web系统变大的过程,实际上就是我们解决问题的过程。在不同的阶段,解决不同的问题,而新的问题又诞生在旧的解决方案之上。 系统的优化是没有极限的,软件和系统架构也一直在快速发展,新的方案解决了老的问题,同时也带来新的挑战。
作者:微信小助手
<section class="output_wrapper" data-mpa-powered-by="yiban.io"> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-bottom: 1.5em;margin-top: 5px;">序列化是一种对象持久化的手段。普遍应用在网络传输、RMI等场景中。类通过实现 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">java.io.Serializable</code> 接口以启用其序列化功能。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在我的博客中,其实已经有多篇文章介绍过序列化了,对序列化的基础知识不够了解的朋友可以参考以下几篇文章:</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><a href="http://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650120836&idx=1&sn=c83a980c0871faf607ae613092c69760&chksm=f36bbfa5c41c36b317c103f27b9d99c26aecba52e4bf614bd73dcadc1e4bc5ab8f99fb082eba&scene=21#wechat_redirect" target="_blank" data-linktype="2">Java对象的序列化与反序列化</a><br><a href="http://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650120882&idx=1&sn=8e355b5ee3cce0a2d0108edbdf88e606&chksm=f36bbf93c41c3685340d4f658dddec6bcbd5903b5d92875bb06d51a0dfc49ee7326417a0edff&scene=21#wechat_redirect" target="_blank" data-linktype="2">深入分析Java的序列化与反序列化</a><br><a href="http://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650120643&idx=1&sn=72ffc1018f5fe4451f885be56e972b30&chksm=f36bbce2c41c35f4d18a841b6fcc5688e7ab3d520be46bc72825b16c0d507a31e48f77dcf0fa&scene=21#wechat_redirect" target="_blank" data-linktype="2">单例与序列化的那些事儿</a></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在这几篇文章中,我分别介绍过了序列化涉及到的类和接口、如何自定义序列化策略、transient关键字和序列化的关系等,还通过学习ArrayList对序列化的实现源码深入学习了序列化。并且还拓展分析了一下序列化对单例的影响等。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">但是,还有一个知识点并未展开介绍,那就是关于<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">serialVersionUID</code> 。这个字段到底有什么用?如果不设置会怎么样?为什么《阿里巴巴Java开发手册》中有以下规定:</p> <p style="font-size: inherit;color: inherit;margin-bottom: 5px;margin-top: 5px;line-height: normal;"><img class="" data-ratio="0.15310492505353318" src="/upload/a852e512cf5a70fc0e656fae7afa54db.null" data-type="jpeg" data-w="1868"></p> <section class="mpa-template" data-mpa-template-id="1120346" data-mpa-color="null" data-mpa-category="收藏"> <section data-mpa-template-id="1115154" data-mpa-color="null" data-mpa-category="fav" style="color: rgb(0, 0, 0);font-size: medium;"> <section> <section> <section class="mpa-template" data-mpa-template-id="1120345" data-mpa-color="null" data-mpa-category="fav"> <section> <section class="Powered-by-XIUMI V5" powered-by="xiumi.us" style=""> <section class="" style="margin-top: 10px;margin-bottom: 10px;"> <section class="" style="margin-left: 0.8em;float: left;"> <section class="" style="width: 2.5em;display: inline-block;vertical-align: bottom;overflow: hidden !important;"> <img data-ratio="0.9166667" src="/upload/e3fa31388d906855ab7742b2895e513c.null" data-w="60" style="vertical-align: middle;height: auto !important;"> </section> <section class="" style="margin-top: 0.5em;display: inline-block;vertical-align: top;font-size: 24px;"> <section mpa-is-content="t"> <span style="font-size: 17px;" mpa-is-content="t">背景知识</span> </section> </section> </section> <img class="" data-ratio="0.0057143" src="/upload/4e3025334c53f646db8e05c54cb43123.null" data-w="700" style="width: 557.778px;float: left;display: inline-block;vertical-align: middle;background-color: rgb(160, 160, 160);height: auto !important;"> <section class="" style="clear: both;"></section> </section> <p>在展开本文的介绍之前,先来简单介绍一些和序列化有关的知识,内容均来自文章开头的三个文章链接中。</p> <p><strong style="color: inherit;font-size: inherit;line-height: inherit;"><br></strong></p> <p><strong style="color: inherit;font-size: inherit;line-height: inherit;">Serializable 和 Externalizable</strong><br></p> </section> </section> </section> </section> </section> </section> </section> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Java类通过实现 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">java.io.Serializable</code> 接口以启用其序列化功能。<strong style="font-size: inherit;color: inherit;line-height: inherit;">未实现此接口的类将无法进行序列化或反序列化。</strong>可序列化类的所有子类型本身都是可序列化的。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">如果读者看过<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Serializable</code>的源码,就会发现,他只是一个空的接口,里面什么东西都没有。<strong style="font-size: inherit;color: inherit;line-height: inherit;">Serializable接口没有方法或字段,仅用于标识可序列化的语义。</strong>但是,如果一个类没有实现这个接口,想要被序列化的话,就会抛出<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">java.io.NotSerializableException</code>异常。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">它是怎么保证只有实现了该接口的方法才能进行序列化与反序列化的呢?</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">原因是在执行序列化的过程中,会执行到以下代码:</p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;" class="hljs-default"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 14px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">if</span> (obj <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 72px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">instanceof</span> <span class="hljs-default-built_in" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">String</span>) {<br> writeString((<span class="hljs-default-built_in" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">String</span>) obj, unshared);<br>} <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">else</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 15px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">if</span> (cl.isArray()) {<br> writeArray(obj, desc, unshared);<br>} <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">else</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 15px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">if</span> (obj <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 72px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">instanceof</span> Enum) {<br> writeEnum((Enum<?>) obj, desc, unshared);<br>} <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">else</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 15px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">if</span> (obj <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 72px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">instanceof</span> Serializable) {<br> writeOrdinaryObject(obj, desc, unshared);<br>} <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">else</span> {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 14px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">if</span> (extendedDebugInfo) {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">throw</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 22px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">new</span> NotSerializableException(<br> cl.getName() + <span class="hljs-default-string" style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"\n"</span> + debugInfoStack.toString());<br> } <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">else</span> {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">throw</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 22px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">new</span> NotSerializableException(cl.getName());<br> }<br>}</code></pre> </section> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在进行序列化操作时,会判断要被序列化的类是否是<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Enum</code>、<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Array</code>和<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Serializable</code>类型,如果都不是则直接抛出<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">NotSerializableException</code>。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Java中还提供了<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Externalizable</code>接口,也可以实现它来提供序列化能力。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Externalizable</code>继承自<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Serializable</code>,该接口中定义了两个抽象方法:<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">writeExternal()</code>与<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">readExternal()</code>。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">当使用<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Externalizable</code>接口来进行序列化与反序列化的时候需要开发人员重写<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">writeExternal()</code>与<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">readExternal()</code>方法。否则所有变量的值都会变成默认值。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">transient</strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">transient</code> 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">transient</code> 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">自定义序列化策略</strong></p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在序列化过程中,如果被序列化的类中定义了<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">writeObject</code> 和 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">readObject</code> 方法,虚拟机会试图调用对象类里的 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">writeObject</code> 和 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">readObject</code> 方法,进行用户自定义的序列化和反序列化。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">如果没有这样的方法,则默认调用是 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">ObjectOutputStream</code> 的 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">defaultWriteObject</code> 方法以及 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">ObjectInputStream</code> 的 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">defaultReadObject</code> 方法。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">用户自定义的 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">writeObject</code> 和 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">readObject</code> 方法可以允许用户控制序列化的过程,比如可以在序列化的过程中动态改变序列化的数值。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">所以,对于一些特殊字段需要定义序列化的策略的时候,可以考虑使用transient修饰,并自己重写<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">writeObject</code> 和 <code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">readObject</code> 方法,如<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">java.util.ArrayList</code>中就有这样的实现。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">以上,就是一些读者需要掌握和和序列化有关的知识。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">我们随便找几个Java中实现了序列化接口的类,如String、Integer等,我们可以发现一个细节,那就是这些类除了实现了<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Serializable</code>外,还定义了一个<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">serialVersionUID</code><br></p> <p><img class="" data-ratio="0.27191679049034173" src="/upload/e1da378cb92b76dabb6d4bc572dabbfb.null" data-type="jpeg" data-w="673"></p> <figure style="font-size: inherit;color: inherit;line-height: inherit;"></figure> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">那么,到底什么是<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">serialVersionUID</code>呢?为什么要设置这样一个字段呢?</p> <section class="mpa-template" data-mpa-template-id="1120346" data-mpa-color="null" data-mpa-category="收藏"> <section data-mpa-template-id="1115154" data-mpa-color="null" data-mpa-category="fav" style="color: rgb(0, 0, 0);font-size: medium;"> <section> <section> <section class="mpa-template" data-mpa-template-id="1120345" data-mpa-color="null" data-mpa-category="fav"> <section> <section class="Powered-by-XIUMI V5" powered-by="xiumi.us" style=""> <section class="" style="margin-top: 10px;margin-bottom: 10px;"> <section class="" style="margin-left: 0.8em;float: left;"> <section class="" style="width: 2.5em;display: inline-block;vertical-align: bottom;overflow: hidden !important;"> <img data-ratio="0.9166667" src="/upload/e3fa31388d906855ab7742b2895e513c.null" data-w="60" style="vertical-align: middle;height: auto !important;"> </section> <section class="" style="margin-top: 0.5em;display: inline-block;vertical-align: top;font-size: 24px;"> <section mpa-is-content="t"> <span style="font-size: 17px;" mpa-is-content="t">什么是serialVersionUID</span> </section> </section> </section> <img class="" data-ratio="0.0057143" src="/upload/4e3025334c53f646db8e05c54cb43123.null" data-w="700" style="width: 557.778px;float: left;display: inline-block;vertical-align: middle;background-color: rgb(160, 160, 160);height: auto !important;"> <section class="" style="clear: both;"></section> </section> <p><span style="font-size: 16px;">序列化是将对象的状态信息转换为可存储或传输的形式的过程。我们都知道,Java对象是保存在JVM的堆内存中的,也就是说,如果JVM堆不存在了,那么对象也就跟着消失了。</span><br></p> </section> </section> </section> </section> </section> </section> </section> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">而序列化提供了一种方案,可以让你在即使JVM停机的情况下也能把对象保存下来的方案。就像我们平时用的U盘一样。把Java对象序列化成可存储或传输的形式(如二进制流),比如保存在文件中。这样,当再次需要这个对象的时候,从文件中读取出二进制流,再从二进制流中反序列化出对象。</p> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong>虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致</strong>,这个所谓的序列化ID,就是我们在代码中定义的<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">serialVersionUID</code>。</p> <section class="mpa-template" data-mpa-template-id="1120346" data-mpa-color="null" data-mpa-category="收藏"> <section data-mpa-template-id="1115154" data-mpa-color="null" data-mpa-category="fav" style="color: rgb(0, 0, 0);font-size: medium;"> <section> <section> <section class="mpa-template" data-mpa-template-id="1120345" data-mpa-color="null" data-mpa-category="fav"> <section> <section class="Powered-by-XIUMI V5" powered-by="xiumi.us" style=""> <section class="" style="margin-top: 10px;margin-bottom: 10px;"> <section class="" style="margin-left: 0.8em;float: left;"> <section class="" style="width: 2.5em;display: inline-block;vertical-align: bottom;overflow: hidden !important;"> <img data-ratio="0.9166667" src="/upload/e3fa31388d906855ab7742b2895e513c.null" data-w="60" style="vertical-align: middle;height: auto !important;"> </section> <section class="" style="margin-top: 0.5em;display: inline-block;vertical-align: top;font-size: 24px;"> <section mpa-is-content="t"> <span style="font-size: 17px;" mpa-is-content="t">如果serialVersionUID变了会怎样</span> </section> </section> </section> <img class="" data-ratio="0.0057143" src="/upload/4e3025334c53f646db8e05c54cb43123.null" data-w="700" style="width: 557.778px;float: left;display: inline-block;vertical-align: middle;background-color: rgb(160, 160, 160);height: auto !important;"> <section class="" style="clear: both;"></section> </section> <p><span style="color: inherit;font-size: 16px;">我们举个例子吧,看看如果</span><code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);"><span style="font-size: 16px;">serialVersionUID</span></code><span style="color: inherit;font-size: 16px;">被修改了会发生什么?</span></p> <p><span style="color: inherit;font-size: 16px;"><br></span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;" class="hljs-default"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span class="hljs-default-class" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 174px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span class="hljs-default-title" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 123px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">SerializableDemo1</span> </span>{<br> <span class="hljs-default-function" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 281px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 44px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">static</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">main</span><span class="hljs-default-params" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 108px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">(String[] args)</span> </span>{<br> <span class="hljs-default-comment" style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline;width: 173px;text-decoration: none solid rgb(92, 99, 112);font-weight: 400;font-style: italic;">//Initializes The Object</span><br> User1 user = <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 21px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">new</span> User1();<br> user.setName(<span class="hljs-default-string" style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 57px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"hollis"</span>);<br> <span class="hljs-default-comment" style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline;width: 137px;text-decoration: none solid rgb(92, 99, 112);font-weight: 400;font-style: italic;">//Write Obj to File</span><br> ObjectOutputStream oos = <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">null</span>;<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 21px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">try</span> {<br> oos = <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 22px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">new</span> ObjectOutputStream(<span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 22px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">new</span> FileOutputStream(<span class="hljs-default-string" style="color: rgb(152, 195, 121);background: rgba(0, 0, 0, 0);display: inline;width: 72px;text-decoration: none solid rgb(152, 195, 121);font-weight: 400;font-style: normal;">"tempFile"</span>));<br> oos.writeObject(user);<br> } <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">catch</span> (IOException e) {<br> e.printStackTrace();<br> } <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 51px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">finally</span> {<br> IOUtils.closeQuietly(oos);<br> }<br> }<br>}<br><br><span class="hljs-default-class" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 260px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span class="hljs-default-title" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">User1</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 73px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">implements</span> <span class="hljs-default-title" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 87px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">Serializable</span> </span>{<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 50px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 44px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">static</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">final</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">long</span> serialVersionUID = <span class="hljs-default-number" style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 14px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">1L</span>;<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 50px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> String name;<br> <span class="hljs-default-function" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 173px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> String <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 50px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">getName</span><span class="hljs-default-params" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 15px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">()</span> </span>{<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">return</span> name;<br> }<br> <span class="hljs-default-function" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 238px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 51px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">setName</span><span class="hljs-default-params" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 94px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">(String name)</span> </span>{<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 28px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">this</span>.name = name;<br> }<br> }</code></pre> </section> </section> </section> </section> </section> </section> </section> </section> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">我们先执行以上代码,把一个User1对象写入到文件中。然后我们修改一下User1类,把<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">serialVersionUID</code>的值改为<code style="font-size: inherit;line-height: inherit;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">2L</code>。</p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;" class="hljs-default"><span class="hljs-default-class" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 260px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span class="hljs-default-title" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">User1</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 73px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">implements</span> <span class="hljs-default-title" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 87px;text-decoration: none solid rgb(230, 192, 123);font-weight: 400;font-style: normal;">Serializable</span> </span>{<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 50px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 44px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">static</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 36px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">final</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">long</span> serialVersionUID = <span class="hljs-default-number" style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 14px;text-decoration: none solid rgb(209, 154, 102);font-weight: 400;font-style: normal;">2L</span>;<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 50px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> String name;<br> <span class="hljs-default-function" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 173px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> String <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 50px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">getName</span><span class="hljs-default-params" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 15px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">()</span> </span>{<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">return</span> name;<br> }<br> <span class="hljs-default-function" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 238px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 29px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 51px;text-decoration: none solid rgb(97, 174, 238);font-weight: 400;font-style: normal;">setName</span><span class="hljs-default-params" style="color: rgb(171, 178, 191);background: rgba(0, 0, 0, 0);display: inline;width: 94px;text-decoration: none solid rgb(171, 178, 191);font-weight: 400;font-style: normal;">(String name)</span> </span>{<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 28px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">this</span>.name = name;<br> }<br>}</code></pre> </section> <p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">然后执行以下代码,把文件中的对象反序列化出来:</p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t"> <pre style="margin:0;padding:0;border-radius:none;background:none;"><code style="border-radius: 4px;font-size: 0.85em;margin: 0px 0.15em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;padding: 6px;overflow-x: auto;white-space: nowrap;" class="hljs-default"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 43px;text-decoration: none solid rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;wi
作者:微信小助手
<section class="" style="padding-right: 10px;padding-left: 9px;max-width: 100%;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;line-height: 1.8;z-index: 10000;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <span style="color: rgb(61, 170, 214);"><img class="" data-croporisrc="/upload/ca27ec1f56ea6e6887423a593f5962e2.jpg" data-cropx1="0" data-cropx2="1024" data-cropy1="43.54015748031496" data-cropy2="677.2913385826771" data-ratio="0.619140625" src="https://mmbiz.qpic.cn/mmbiz_jpg/l89kosVutolkw9OONDFicgCwslEWdhAJicXY58hCkUkX9jVDdcQSuiaVKOGflSutU10mIu2INSpn4OnHCxibJkrZdA/640?wx_fmt=jpeg" data-type="jpeg" data-w="1024" style="width: 635px;height: 393px;"></span> </section> <section class="" style="padding-right: 10px;padding-left: 9px;max-width: 100%;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;line-height: 1.8;z-index: 10000;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <span style="color: rgb(61, 170, 214);"><br></span> </section> <section class="" style="padding-right: 10px;padding-left: 9px;max-width: 100%;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;line-height: 1.8;z-index: 10000;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <span style="color: rgb(61, 170, 214);">导读</span> </section> <p style="max-width: 100%;min-height: 1em;white-space: normal;letter-spacing: 0.544px;text-size-adjust: auto;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-ratio="0.053125" src="/upload/16c3bc26d4547f0344ee22af769e1434.png" data-type="png" data-w="640" style="color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: 632px !important;"></p> <p style="white-space: normal;text-align: left;line-height: 2em;"><span style="font-size: 15px;background-color: rgb(255, 255, 255);font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;text-align: start;">在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下:<br></span></p> <p style="white-space: normal;text-align: left;line-height: 2em;"><span style="font-size: 15px;">1.公平锁 / 非公平锁</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">2.可重入锁 / 不可重入锁</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">3.独享锁 / 共享锁</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">4.互斥锁 / 读写锁</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">5.乐观锁 / 悲观锁</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">6.分段锁</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">7.偏向锁 / 轻量级锁 / 重量级锁</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">8.自旋锁</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释。</span></p> <section class="" style="padding-right: 10px;padding-left: 9px;max-width: 100%;white-space: normal;background-color: rgb(255, 255, 255);color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;line-height: 1.8;z-index: 10000;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <span style="color: rgb(61, 170, 214);">公平锁/非公平锁</span> </section> <p style="max-width: 100%;min-height: 1em;white-space: normal;letter-spacing: 0.544px;text-size-adjust: auto;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-ratio="0.053125" src="/upload/16c3bc26d4547f0344ee22af769e1434.png" data-type="png" data-w="640" style="color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: 632px !important;"></p> <p style="max-width: 100%;min-height: 1em;white-space: normal;letter-spacing: 0.544px;text-size-adjust: auto;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="font-size: 15px;"><strong style="font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;">公平锁</strong></span></p> <p style="white-space: normal;"><span style="font-size: 16px;"><br></span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">公平锁是指多个线程按照申请锁的顺序来获取锁。</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Microsoft YaHei', 'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);"><strong>非公平锁</strong></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;">非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。</span></p> <p style="white-space: normal;line-height: 2em;"><span style="font-size: 15px;"><br></span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">对于</span><code style="padding: 2px 4px;font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace;font-size: 0.93em;color: rgb(199, 37, 78);background-color: rgb(249, 242, 244);border-radius: 4px;"><span style="font-size: 15px;">Java ReentrantLock</span></code><span style="font-size: 15px;">而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;"><br>对于</span><code style="padding: 2px 4px;font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace;font-size: 0.93em;color: rgb(199, 37, 78);background-color: rgb(249, 242, 244);border-radius: 4px;"><span style="font-size: 15px;">Synchronized</span></code><span style="font-size: 15px;">而言,也是一种非公平锁。由于其并不像</span><code style="padding: 2px 4px;font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace;font-size: 0.93em;color: rgb(199, 37, 78);background-color: rgb(249, 242, 244);border-radius: 4px;"><span style="font-size: 15px;">ReentrantLock</span></code><span style="font-size: 15px;">是通过</span><code style="padding: 2px 4px;font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace;font-size: 0.93em;color: rgb(199, 37, 78);background-color: rgb(249, 242, 244);border-radius: 4px;"><span style="font-size: 15px;">AQS</span></code><span style="font-size: 15px;">的来实现线程调度,所以并没有任何办法使其变成公平锁。</span></p> <section class="" style="padding-right: 10px;padding-left: 9px;white-space: normal;max-width: 100%;background-color: rgb(255, 255, 255);color: rgb(60, 60, 60);font-size: 16px;font-weight: bold;letter-spacing: 1px;text-align: center;line-height: 1.8;z-index: 10000;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"> <span style="color: rgb(61, 170, 214);">可重入锁/不可重入锁</span> </section> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;text-size-adjust: auto;box-sizing: border-box !important;word-wrap: break-word !important;"><img class="" data-ratio="0.053125" src="/upload/16c3bc26d4547f0344ee22af769e1434.png" data-type="png" data-w="640" style="color: rgb(60, 60, 60);font-weight: bold;letter-spacing: 1px;text-align: center;background-color: rgb(255, 255, 255);font-size: 15px;display: inline-block;left: 0px;transform: rotateX(60deg);margin-top: 5px !important;box-sizing: border-box !important;word-wrap: break-word !important;visibility: visible !important;width: 632px !important;"></p> <h2 style="white-space: normal;"><strong style="font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;">可重入锁</strong><br></h2> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁。</span><code style="padding: 2px 4px;font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace;font-size: 0.93em;color: rgb(199, 37, 78);background-color: rgb(249, 242, 244);border-radius: 4px;"><span style="font-size: 15px;">ReentrantLock</span></code><span style="font-size: 15px;">和</span><code style="padding: 2px 4px;font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace;font-size: 0.93em;color: rgb(199, 37, 78);background-color: rgb(249, 242, 244);border-radius: 4px;"><span style="font-size: 15px;">synchronized</span></code><span style="font-size: 15px;">都是可重入锁</span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t" style="white-space: normal;"> <pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;background-image: none;background-color: initial;"><code class="hljs-default" style="margin-right: 0.15em;margin-left: 0.15em;padding: 6px;border-radius: 4px;font-size: 0.85em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;overflow-x: auto;white-space: nowrap;"><span class="hljs-default-function" style="background: rgba(0, 0, 0, 0);display: inline;width: 270px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">synchronized</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(97, 174, 238);">setA</span><span class="hljs-default-params" style="background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);">()</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">throws</span> Exception</span>{<br> Thread.sleep(<span class="hljs-default-number" style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(209, 154, 102);">1000</span>);<br> setB();<br>}<br><span class="hljs-default-function" style="background: rgba(0, 0, 0, 0);display: inline;width: 270px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 79px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">synchronized</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(97, 174, 238);">setB</span><span class="hljs-default-params" style="background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);">()</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">throws</span> Exception</span>{<br> Thread.sleep(<span class="hljs-default-number" style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(209, 154, 102);">1000</span>);<br>}</code></pre> </section> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">上面的代码就是一个可重入锁的一个特点,如果不是可重入锁的话,setB可能不会被当前线程执行,可能造成死锁。</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Microsoft YaHei', 'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);"><strong>不可重入锁</strong></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">不可重入锁,与可重入锁相反,不可递归调用,递归调用就发生死锁。看到一个经典的讲解,使用自旋锁来模拟一个不可重入锁,代码如下:</span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t" style="white-space: normal;"> <pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;background-image: none;background-color: initial;"><code class="hljs-default" style="margin-right: 0.15em;margin-left: 0.15em;padding: 6px;border-radius: 4px;font-size: 0.85em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;overflow-x: auto;white-space: nowrap;"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">import</span> java.util.concurrent.atomic.AtomicReference;<br><br><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">public</span> <span class="hljs-default-class" style="background: rgba(0, 0, 0, 0);display: inline;width: 145px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">class</span> <span class="hljs-default-title" style="color: rgb(230, 192, 123);background: rgba(0, 0, 0, 0);display: inline;width: 99px;text-decoration-style: solid;text-decoration-color: rgb(230, 192, 123);">UnreentrantLock</span> </span>{<br><br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">private</span> AtomicReference<Thread> owner = <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">new</span> AtomicReference<Thread>();<br><br> <span class="hljs-default-function" style="background: rgba(0, 0, 0, 0);display: inline;width: 126px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration-style: solid;text-decoration-color: rgb(97, 174, 238);">lock</span><span class="hljs-default-params" style="background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);">()</span> </span>{<br> Thread current = Thread.currentThread();<br> <span class="hljs-default-comment" style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline;width: 292px;text-decoration-style: solid;text-decoration-color: rgb(92, 99, 112);font-style: italic;">//这句是很经典的“自旋”语法,AtomicInteger中也有</span><br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 19px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">for</span> (;;) {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">if</span> (!owner.compareAndSet(<span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">null</span>, current)) {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">return</span>;<br> }<br> }<br> }<br><br> <span class="hljs-default-function" style="background: rgba(0, 0, 0, 0);display: inline;width: 139px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(97, 174, 238);">unlock</span><span class="hljs-default-params" style="background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);">()</span> </span>{<br> Thread current = Thread.currentThread();<br> owner.compareAndSet(current, <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">null</span>);<br> }<br>}</code></pre> </section> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">代码也比较简单,使用原子引用来存放线程,同一线程两次调用lock()方法,如果不执行unlock()释放锁的话,第二次调用自旋的时候就会产生死锁,这个锁就不是可重入的,而实际上同一个线程不必每次都去释放锁再来获取锁,这样的调度切换是很耗资源的。</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'PingFang SC', 'Microsoft YaHei', 'Source Han Sans SC', 'Noto Sans CJK SC', 'WenQuanYi Micro Hei', sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);"><strong>把它变成一个可重入锁</strong>:</p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t" style="white-space: normal;"> <pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;background-image: none;background-color: initial;"><code class="hljs-default" style="margin-right: 0.15em;margin-left: 0.15em;padding: 6px;border-radius: 4px;font-size: 0.85em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;overflow-x: auto;white-space: nowrap;">import java.util.concurrent.atomic.AtomicReference;<br><br><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 39px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">class</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 99px;text-decoration-style: solid;text-decoration-color: rgb(97, 174, 238);">UnreentrantLock</span> {<br><br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">private</span> AtomicReference<Thread> owner = <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">new</span> AtomicReference<Thread>();<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 46px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">private</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">int</span> state = <span class="hljs-default-number" style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 7px;text-decoration-style: solid;text-decoration-color: rgb(209, 154, 102);">0</span>;<br><br> <span class="hljs-default-function" style="background: rgba(0, 0, 0, 0);display: inline;width: 126px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration-style: solid;text-decoration-color: rgb(97, 174, 238);">lock</span>() </span>{<br> Thread current = Thread.currentThread();<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">if</span> (current == owner.<span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">get</span>()) {<br> state++;<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">return</span>;<br> }<br> <span class="hljs-default-comment" style="color: rgb(92, 99, 112);background: rgba(0, 0, 0, 0);display: inline;width: 304px;text-decoration-style: solid;text-decoration-color: rgb(92, 99, 112);font-style: italic;">//这句是很经典的“自旋”式语法,AtomicInteger中也有</span><br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 19px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">for</span> (;;) {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">if</span> (!owner.compareAndSet(<span class="hljs-default-literal" style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(86, 182, 194);">null</span>, current)) {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">return</span>;<br> }<br> }<br> }<br><br> <span class="hljs-default-function" style="background: rgba(0, 0, 0, 0);display: inline;width: 139px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">public</span> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">void</span> <span class="hljs-default-title" style="color: rgb(97, 174, 238);background: rgba(0, 0, 0, 0);display: inline;width: 40px;text-decoration-style: solid;text-decoration-color: rgb(97, 174, 238);">unlock</span>() </span>{<br> Thread current = Thread.currentThread();<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">if</span> (current == owner.<span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 20px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">get</span>()) {<br> <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 13px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">if</span> (state != <span class="hljs-default-number" style="color: rgb(209, 154, 102);background: rgba(0, 0, 0, 0);display: inline;width: 6px;text-decoration-style: solid;text-decoration-color: rgb(209, 154, 102);">0</span>) {<br> state--;<br> } <span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 27px;text-decoration-style: solid;text-decoration-color: rgb(198, 120, 221);">else</span> {<br> owner.compareAndSet(current, <span class="hljs-default-literal" style="color: rgb(86, 182, 194);background: rgba(0, 0, 0, 0);display: inline;width: 26px;text-decoration-style: solid;text-decoration-color: rgb(86, 182, 194);">null</span>);<br> }<br> }<br> }<br>}</code></pre> </section> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">在执行每次操作之前,判断当前锁持有者是否是当前对象,采用state计数,不用每次去释放锁。</span></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><strong>ReentrantLock中可重入锁实现</strong></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;white-space: normal;font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", "Source Han Sans SC", "Noto Sans CJK SC", "WenQuanYi Micro Hei", sans-serif;font-size: 15px;text-align: start;background-color: rgb(255, 255, 255);line-height: 2em;"><span style="font-size: 15px;">这里看非公平锁的锁获取方法:</span></p> <section data-mpa-preserve-tpl-color="t" data-mpa-template="t" class="mpa-template" mpa-preserve="t" style="white-space: normal;"> <pre style="margin-top: 0px;margin-bottom: 0px;padding: 0px;background-image: none;background-color: initial;"><code class="hljs-default" style="margin-right: 0.15em;margin-left: 0.15em;padding: 6px;border-radius: 4px;font-size: 0.85em;background: rgb(40, 44, 52);color: rgb(171, 178, 191);display: block;overflow-x: auto;white-space: nowrap;"><span class="hljs-default-function" style="background: rgba(0, 0, 0, 0);display: inline;width: 303px;text-decoration-style: solid;text-decoration-color: rgb(171, 178, 191);"><span class="hljs-default-keyword" style="color: rgb(198, 120, 221);background: rgba(0, 0, 0, 0);display: inline;width: 33px;text-decoration-style: solid;text-decoration-color: rgb(198, 1
作者:微信小助手
<p><br></p> <section data-role="outer" label="Powered by 135editor.com" style="font-size:16px;" data-mpa-powered-by="yiban.io"> <section data-role="outer" label="Powered by 135editor.com"> <section class="_135editor" data-tools="135编辑器" data-id="90196" style="border-width: 0px;border-style: none;border-color: initial;text-align: center;box-sizing: border-box;"> <section style="margin: 8px;padding: 10px;line-height: 25.6px;white-space: normal;border-radius: 10px;height: auto;box-shadow: #dddddd 2px 2px 8px;display: -webkit-flex;box-sizing: border-box;"> <section style="flex: 0 0 2cm;height: 78px;width:75px;"> <section data-role="circle" style="border-radius: 100%;overflow: hidden;margin-right: auto;margin-left: auto;width: 100%;padding-bottom: 100%;height: 0px;background-image: url("/upload/4af79153f7cafe28ac05ebc052d5e06c.jpg");background-position: 50% 50%;background-size: cover;box-sizing: border-box;"> <img class="" data-ratio="0.59" data-type="jpeg" data-w="1200" height="45" src="/upload/4af79153f7cafe28ac05ebc052d5e06c.jpg" style="opacity: 0;width: 76px;height: 45px;" width="76"> </section> </section> <section style="padding-right: 10px;padding-left: 10px;flex: 1 1 auto;height: 55px;box-sizing: border-box;"> <section style="line-height: 35px;white-space: nowrap;text-align: left;"> <strong style="max-width: 100%;color: #548dd4;font-size: 15px;letter-spacing: 0.544px;text-align: justify;white-space: normal;"> <span style="font-size: 16px;">JAVA</span></strong> </section> <section style="font-size: 13px;line-height: 20px;color: #7f7f7f;text-align: left;"> <span style="font-size: 14px;">海量资源/编程技术</span> </section> </section> </section> </section> </section> </section> <p><br></p> <p><span style="font-size: 16px;">在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。</span></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 1. 尽量在合适的场合使用单例</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">第一,控制资源的使用,通过线程同步来控制资源的并发访问;</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">第二,控制实例的产生,以达到节约资源的目的;</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 2. 尽量避免随意使用静态变量</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">当某个对象被定义为static变量所引用,那么GC通常是不会回收这个对象所占有的内存,如</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.1019786910197869" data-w="657" src="/upload/835d5516f57e96565b29ddf24b40902a.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻内存,直到程序终止。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 3. 尽量避免过多过常地创建Java对象</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最大限度地重用对象,最好能用基本的数据类型或数组来替代对象。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 4. 尽量使用final修饰符</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如java、lang、String,为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关),此举能够使性能平均提高50%。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如:让访问实例内变量的getter/setter方法变成”final:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”,例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.37709923664122136" data-w="655" src="/upload/c3cc1ce0a06b069eb09cad89d66feb23.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 5. 尽量使用局部变量</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快;其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 6. 尽量处理好包装类型和基本类型两者的使用场所</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">虽然包装类型和基本类型在使用过程中是可以相互转换,但它们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。在集合类对象,有对象方面需要的处理适用包装类型,其他的处理提倡使用基本类型。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 7. 慎用synchronized,尽量减小synchronize的方法</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">都知道,实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。synchronize方法被调用时,直接会把当前对象锁了,在方法执行完之前其他线程无法调用当前对象的其他方法。所以,synchronize的方法尽量减小,并且应尽量使用方法同步代替代码块同步。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 9. 尽量不要使用finalize方法</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">实际上,将资源清理放在finalize方法中完成是非常不好的选择,由于GC的工作量很大,尤其是回收Young代内存时,大都会引起应用程序暂停,所以再选择使用finalize方法进行资源清理,会导致GC负担更大,程序运行效率更差。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 10. 尽量使用基本数据类型代替对象</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.04732824427480916" data-w="655" src="/upload/4ca5b12f79551629549f956c2edf37e4.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">上面这种方式会创建一个“hello”字符串,而且JVM的字符缓存池还会缓存这个字符串;</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.0487062404870624" data-w="657" src="/upload/e95f55a0659c51962ea12ab1671bda8e.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">此时程序除创建字符串外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组依次存放了h,e,l,l,o</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 11. 多线程在未发生线程安全前提下应尽量使用HashMap、ArrayList</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">HashTable、Vector等使用了同步机制,降低了性能。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 12. 尽量合理的创建HashMap</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">当你要创建一个比较大的hashMap时,充分利用这个构造函数</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.04754601226993865" data-w="652" src="/upload/e0d0fc01fe17e37c689f06f8a9dc3918.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">避免HashMap多次进行了hash重构,扩容是一件很耗费性能的事,在默认中initialCapacity只有16,而loadFactor是 0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的Hashtable,Vectors也是一样的道理。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 13. 尽量减少对变量的重复计算</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.0486322188449848" data-w="658" src="/upload/be855f99f1bf0498c65bd2e1a159e0fb.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">应该改为:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.05030487804878049" data-w="656" src="/upload/143002939b47e65c78acdede5bff1a91.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 14. 尽量避免不必要的创建</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.13016845329249618" data-w="653" src="/upload/c4d4686f507259cdb9195745e911d6ee.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">应该改为:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.1267175572519084" data-w="655" src="/upload/4ffbb3aaa8978a5a3e041eaa74068351.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 15. 尽量在finally块中释放资源</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">程序中使用到的资源应当被释放,以避免资源泄漏,这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 16. 尽量使用移位来代替'a/b'的操作</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">"/"是一个代价很高的操作,使用移位的操作将会更快和更有效</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.07317073170731707" data-w="656" src="/upload/ffe68eb11c859221f96a86eae04fe9e4.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">应该改为:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.07633587786259542" data-w="655" src="/upload/7d0f2dcde77e95b886dcd1a5d2f94358.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">但注意的是使用移位应添加注释,因为移位操作不直观,比较难理解。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 17.尽量使用移位来代替'a*b'的操作</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">同样的,对于'*'操作,使用移位的操作将会更快和更有效</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.0730593607305936" data-w="657" src="/upload/f0c21b73cf842fc1dfa5e2ae8026a5b0.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">应该改为:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.07774390243902439" data-w="656" src="/upload/983e38c9dd16099ef7f3515ea0d337e4.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 18. 尽量确定StringBuffer的容量</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.045941807044410414" data-w="653" src="/upload/97febd831753692945eccbc1736cd2c1.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">●19. 尽量早释放无用对象的引用</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">大部分时,方法局部引用变量所引用的对象会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">例如:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">Java代码</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.15902140672782875" data-w="654" src="/upload/47963f49db24ab42be5930675eb8ae09.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">Java代码</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.2115677321156773" data-w="657" src="/upload/4ce503763da3413d55114bcef308ecc6.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">这时候就有必要将obj赋值为null,可以尽早的释放对Object对象的引用。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 20. 尽量避免使用二维数组</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">二维数据占用的内存空间比一维数组多得多,大概10倍以上。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 21. 尽量避免使用split</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 22. ArrayList & LinkedList</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">一个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2者得数据结构,对症下药。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 23. 尽量使用System.arraycopy ()代替通过来循环复制数组</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">System.arraycopy() 要比通过循环来复制数组快的多。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 24. 尽量缓存经常使用的对象</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">尽可能将经常使用的对象进行缓存,可以使用数组,或HashMap的容器来进行缓存,但这种方式可能导致系统占用过多的缓存,性能下降,推荐可以使用一些第三方的开源工具,如EhCache,Oscache进行缓存,他们基本都实现了FIFO/FLU等缓存算法。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 25. 尽量避免非常大的内存分配</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">有时候问题不是由当时的堆状态造成的,而是因为分配失败造成的。分配的内存块都必须是连续的,而随着堆越来越满,找到较大的连续块越来越困难。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 26. 慎用异常</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如果您创建一个 Exception ,就得付出代价,好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,你甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常,幸运的是,好的编程习惯已教会我们,不应该不管三七二十一就抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 27. 尽量重用对象</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">特别是String对象的使用中,出现字符串连接情况时应使用StringBuffer代替,由于系统不仅要花时间生成对象,以后可能还需要花时间对这些对象进行垃圾回收和处理。因此生成过多的对象将会给程序的性能带来很大的影响。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 28. 不要重复初始化变量</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">默认情况下,调用类的构造函数时,java会把变量初始化成确定的值,所有的对象被设置成null,整数变量设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类派生时,这一点尤其应该注意,因为用new关键字创建一个对象时,构造函数链中的所有构造函数都会被自动调用。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">这里有个注意,给成员变量设置初始值但需要调用其他方法的时候,最好放在一个方法。比如initXXX()中,因为直接调用某方法赋值可能会因为类尚未初始化而抛空指针异常,如:public int state = this.getState()。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 29. 在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 30. 在java编程过程中,进行数据库连接,I/O流操作,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 31. 过分的创建对象会消耗系统的大量内存,严重时,会导致内存泄漏,因此,保证过期的对象的及时回收具有重要意义。JVM的GC并非十分智能,因此建议在对象使用完毕后,手动设置成null。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 32. 在使用同步机制时,应尽量使用方法同步代替代码块同步。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 33. 不要在循环中使用Try/Catch语句,应把Try/Catch放在循环最外层</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">Error是获取系统错误的类,或者说是虚拟机错误的类。不是所有的错误Exception都能获取到的,虚拟机报错Exception就获取不到,必须用Error获取。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 34. 通过StringBuffer的构造函数来设定它的初始化容量,可以明显提升性能</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">StringBuffer的默认容量为16,当StringBuffer的容量达到最大容量时,它会将自身容量增加到当前的2倍+2,也就是2*n+2。无论何时,只要StringBuffer到达它的最大容量,它就不得不创建一个新的对象数组,然后复制旧的对象数组,这会浪费很多时间。所以给StringBuffer设置一个合理的初始化容量值,是很有必要的!</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 35. 合理使用java.util.Vector</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">Vector与StringBuffer类似,每次扩展容量时,所有现有元素都要赋值到新的存储空间中。Vector的默认存储能力为10个元素,扩容加倍。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">vector.add(index,obj) 这个方法可以将元素obj插入到index位置,但index以及之后的元素依次都要向下移动一个位置(将其索引加 1)。 除非必要,否则对性能不利。同样规则适用于remove(int index)方法,移除此向量中指定位置的元素。将所有后续元素左移(将其索引减 1)。返回此向量中移除的元素。所以删除vector最后一个元素要比删除第1个元素开销低很多。删除所有元素最好用removeAllElements()方法。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">如果要删除vector里的一个元素可以使用 vector.remove(obj);而不必自己检索元素位置,再删除,如int index = indexOf(obj);vector.remove(index)。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 38. 不用new关键字创建对象的实例</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">下面是Factory模式的一个典型实现:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.1324200913242009" data-w="657" src="/upload/fd3506ab823979c90b192e639c818099.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">改进后的代码使用clone()方法:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.15749235474006115" data-w="654" src="/upload/86e170c312703f30e0a3311ebb84a335.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 39. 不要将数组声明为:public static final</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 40. HaspMap的遍历:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.1856925418569254" data-w="657" src="/upload/20aca598f723ab56d3475a298ca9d043.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">利用散列值取出相应的Entry做比较得到结果,取得entry的值之后直接取key和value。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 41. array(数组)和ArrayList的使用</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">array 数组效率最高,但容量固定,无法动态改变,ArrayList容量可以动态增长,但牺牲了效率。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 42. 单线程应尽量使用 HashMap, ArrayList,除非必要,否则不推荐使用HashTable,Vector,它们使用了同步机制,而降低了性能。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 43. StringBuffer,StringBuilder的区别在于</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">java.lang.StringBuffer 线程安全的可变字符序列。一个类似于String的字符串缓冲区,但不能修改。StringBuilder与该类相比,通常应该优先使用StringBuilder类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">为了获得更好的性能,在构造StringBuffer或StringBuilder时应尽量指定她的容量。当然如果不超过16个字符时就不用了。 相同情况下,使用StringBuilder比使用StringBuffer仅能获得10%~15%的性能提升,但却要冒多线程不安全的风险。综合考虑还是建议使用StringBuffer。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 44. 尽量使用基本数据类型代替对象。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 45. 使用具体类比使用接口效率高,但结构弹性降低了,但现代IDE都可以解决这个问题。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 46. 考虑使用静态方法,如果你没有必要去访问对象的外部,那么就使你的方法成为静态方法。它会被更快地调用,因为它不需要一个虚拟函数导向表。这同时也是一个很好的实践,因为它告诉你如何区分方法的性质,调用这个方法不会改变对象的状态。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 47. 应尽可能避免使用内在的GET,SET方法。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 48.避免枚举,浮点数的使用。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">以下举几个实用优化的例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 一、避免在循环条件中使用复杂表达式</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.21189024390243902" data-w="656" src="/upload/8b9dee507ef5bdc1e32446eb123939e.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">更正:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.21341463414634146" data-w="656" src="/upload/e7abc31aa72dfc8c7c53f2f6b5058aac.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 二、为'Vectors' 和 'Hashtables'定义初始大小</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">JVM为Vector扩充大小的时候需要重新创建一个更大的数组,将原原先数组中的内容复制过来,最后,原先的数组再被回收。可见Vector容量的扩大是一个颇费时间的事。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">通常,默认的10个元素大小是不够的。你最好能准确的估计你所需要的最佳大小。例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.29573170731707316" data-w="656" src="/upload/8133883f643bb2bdfcb2458cefba1ec0.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">更正:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">自己设定初始大小。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.0729483282674772" data-w="658" src="/upload/f0af05d931df7e8d8356945a891cfac2.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 三、在finally块中关闭Stream</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 四、使用'System.arraycopy ()'代替通过来循环复制数组</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.3789954337899543" data-w="657" src="/upload/cc127f31b455b749afb3249eb6fc617a.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">更正:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.32164634146341464" data-w="656" src="/upload/81d8f643ca70e8b16b49fb5c32537b69.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 五、让访问实例内变量的getter/setter方法变成”final”</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”,例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.18473282442748093" data-w="655" src="/upload/6691819539c85118a81777698b4471f.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">更正:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.18960244648318042" data-w="654" src="/upload/6add1379c565390163b5e652d7cef6f7.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 六、对于常量字符串,用'String' 代替 'StringBuffer'</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">常量字符串并不需要动态改变长度。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.21100917431192662" data-w="654" src="/upload/cfca3510ec5495e4e27d712851f1ad81.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">更正:把StringBuffer换成String,如果确定这个String不会再变的话,这将会减少运行开销提高性能。</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">● 七、在字符串相加的时候,使用 ' ' 代替 " ",如果该字符串只有一个字符的话</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">例子:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.182648401826484" data-w="657" src="/upload/5916d8b5d45e0cb2540d7815be6ab69.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">更正:</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">将一个字符的字符串替换成' '</p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;"><img class="" data-ratio="0.18501529051987767" data-w="654" src="/upload/3f34211747b45b0c3f765b7aabb15c99.null" style="max-width: 100%;display: block;margin: 20px auto 30px;"></p> <p style="font-size: 16px;line-height: 1.7;color: rgb(51, 51, 51);font-weight: 400;margin: 20px 0px;">以上仅是Java方面编程时的性能优化,性能优化大部分都是在时间、效率、代码结构层次等方面的权衡,各有利弊,不要把上面内容当成教条,或许有些对我们实际工作适用,有些不适用,还望根据实际工作场景进行取舍,活学活用,变通为宜。</p> <blockquote class="js_blockquote_wrap" data-type="2" data-url="" data-author-name="" data-content-utf8-length="2" data-source-title="https://blog.51cto.com/13399166/2363740?source=dra"> <section class="js_blockquote_digest"> <p>原文</p> </section> <section class="blockquote_info js_blockquote_source" data-json="%7B%22type%22%3A%22out%22%2C%22source%22%3A%22url%22%2C%22digest%22%3A%22%3Cp%3E%E5%8E%9F%E6%96%87%3C%2Fp%3E%22%2C%22digestLen%22%3A2%2C%22text%22%3A%22%22%2C%22article%22%3A%7B%7D%2C%22from%22%3A%22https%3A%2F%2Fblog.51cto.com%2F13399166%2F2363740%3Fsource%3Ddra%22%7D"> <span class="blockquote_other">https://blog.51cto.com/13399166/2363740?source=dra</span> </section> </blockquote>
作者:じ☆ve宝贝
在左侧的导航框中点击 KeyMap。 接着在右边的树型框中选择 Main menu –> Code –> **Completion** 接着需要做两件事: 1. 移除原来的**Cycle Expand Word** 的 Alt+斜杠 快捷键绑定 2. 在 Basic 上点击右键,去除原来的 Ctrl+空格 绑定,然后添加 Alt + 斜杠 快捷键。 大功告成
作者:微信小助手
<p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 0, 0);font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">(点击</span><span style="max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);">上方公众号</span><span style="max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">,可快速关注)</span></span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <blockquote style="max-width: 100%;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <p style="max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">来源:zy_lebron ,</span></p> <p style="max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">youngforzy.top/2018/02/15/ActiveMQ结合Spring收发消息/</span></p> </blockquote> <p><br></p> <p><strong><span style="color: rgb(255, 76, 65);">ActiveMQ 结合 Spring 收发消息</span></strong></p> <p><br></p> <p>直接使用 ActiveMQ 的方式需要重复写很多代码,且不利于管理,Spring 提供了一种更加简便的方式————Spring JMS ,通过它可以更加方便地使用 ActiveMQ。</p> <p><br></p> <p><strong><span style="color: rgb(123, 12, 0);">Maven 依赖</span></strong></p> <p><br></p> <p>结合Spring使用ActiveMQ的依赖如下:</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- Spring JMS --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><dependency></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <groupId>org.springframework</groupId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <artifactId>spring-jms</artifactId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <version>${spring.version}</version></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></dependency></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- xbean 如<amq:connectionFactory /> --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><dependency></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <groupId>org.apache.xbean</groupId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <artifactId>xbean-spring</artifactId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <version>3.16</version></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></dependency></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- ActiiveMQ --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><dependency></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <groupId>org.apache.activemq</groupId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <artifactId>activemq-core</artifactId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <version>5.7.0</version></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></dependency></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><dependency></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <groupId>org.apache.activemq</groupId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <artifactId>activemq-pool</artifactId></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <version>5.7.0</version></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></dependency></span></p> </blockquote> <p><br></p> <p>ActiveMQ.xml 文件</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><?xml version="1.0" encoding="UTF-8"?></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><beans xmlns="http://www.springframework.org/schema/beans"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> xmlns:amq="http://activemq.apache.org/schema/core"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> xsi:schemaLocation="http://www.springframework.org/schema/beans</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">http://www.springframework.org/schema/beans/spring-beans-4.0.xsd</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">http://activemq.apache.org/schema/core</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">http://activemq.apache.org/schema/core/activemq-core-5.12.1.xsd"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- ActiveMQ 连接工厂 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <amq:connectionFactory id="amqConnectionFactory"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> brokerURL="tcp://localhost:61616"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> userName="admin"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> password="admin" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- 提高效率,配置JMS连接工厂 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <constructor-arg ref="amqConnectionFactory" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="sessionCacheSize" value="100" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </bean></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- 定义消息队列(Queue)--></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- <bean id="QueueDestination" class="org.apache.activemq.command.ActiveMQQueue"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> &lt;!– 设置消息队列的名字 –&gt;</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <constructor-arg value="Queue-zy"/></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </bean>--></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!--定义主题(Topic)--></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <constructor-arg value="Topic-zy"/></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </bean></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- 配置JMS模板(Queue),Spring提供的JMS工具类,利用它发送、接收消息。 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="connectionFactory" ref="connectionFactory" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="defaultDestination" ref="topicDestination" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="receiveTimeout" value="10000" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- true是topic,false是queue,默认是false --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="pubSubDomain" value="true" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </bean></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- 配置消息队列监听者(Queue or Topic) --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <bean id="messageListener" class="com.service.TopicMessageListener" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- 显示注入消息监听容器,配置连接工厂,监听的目标是QueueDestination,监听器是上面定义的监听器 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <bean id="ListenerContainer"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> class="org.springframework.jms.listener.DefaultMessageListenerContainer"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="connectionFactory" ref="connectionFactory" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="destination" ref="topicDestination" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="messageListener" ref="messageListener" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </bean></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></beans></span></p> </blockquote> <p><br></p> <p><span style="color: rgb(0, 0, 0);"><strong>配置 connectionFactory</strong></span></p> <p><br></p> <p>connectionFactory 是 Spring 用于创建到 JMS 服务器链接的,Spring 提供了多种 connectionFactory。</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- ActiveMQ 连接工厂 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><amq:connectionFactory id="amqConnectionFactory"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> brokerURL="tcp://localhost:61616"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> userName="admin"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> password="admin" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- 提高效率,配置JMS连接工厂 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <constructor-arg ref="amqConnectionFactory" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="sessionCacheSize" value="100" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></bean></span></p> </blockquote> <p><br></p> <p>配置Queue</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><bean id="QueueDestination" class="org.apache.activemq.command.ActiveMQQueue"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- 设置消息队列的名字 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <constructor-arg value="Queue-zy"/></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></bean></span></p> </blockquote> <p><br></p> <p>配置Topic</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <constructor-arg value="Topic-zy"/></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></bean></span></p> </blockquote> <p><br></p> <p>配置JMS消息模板——jmsTemplate</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- 配置JMS模板,Spring提供的JMS工具类,利用它发送、接收消息--></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="connectionFactory" ref="connectionFactory" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="defaultDestination" ref="QueueDestination" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!--<property name="defaultDestination" ref="topicDestination" />--></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="receiveTimeout" value="10000" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="pubSubDomain" value="false" /><!-- true是topic,false是queue,默认是false --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"></bean></span></p> </blockquote> <p><br></p> <p>最后,在 applicationContext.xml 中引入配置好的 ActiveMQ.xml</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><import resource="ActiveMQ.xml" /></span></p> </blockquote> <p><br></p> <p>以上就是配置文件相关的,下面是具体的业务代码。</p> <p><br></p> <p><strong><span style="color: rgb(123, 12, 0);">消息生产者服务</span></strong></p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">@Service</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">public class ProducerService {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> @Autowired</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> private JmsTemplate jmsTemplate;</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> //使用默认目的地</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public void sendMessageDefault(final String msg){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> Destination destination = jmsTemplate.getDefaultDestination();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> System.out.println("向队列: " + destination + " 成功发送一条消息");</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> jmsTemplate.send(new MessageCreator() {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public Message createMessage(Session session) throws JMSException {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> return session.createTextMessage(msg);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> });</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> //可指定目的地</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public void sendMessage(Destination destination,final String msg){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> jmsTemplate.send(destination, new MessageCreator() {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public Message createMessage(Session session) throws JMSException {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> return session.createTextMessage(msg);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> });</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">}</span></p> </blockquote> <p><br></p> <p><strong><span style="color: rgb(123, 12, 0);">消息消费者服务</span></strong></p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">@Service</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">public class ConsumerService {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> @Autowired</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> private JmsTemplate jmsTemplate;</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> //从指定的Destination接收消息</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public TextMessage recive(Destination destination){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> TextMessage message = (TextMessage) jmsTemplate.receive(destination);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> try {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> System.out.println("从队列" + destination.toString() + "收到了消息" + message.getText());</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> } catch (JMSException e) {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> e.printStackTrace();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> return message;</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> //从默认的Destination接收消息</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public void reciveDefault(){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> Destination destination = jmsTemplate.getDefaultDestination();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> jmsTemplate.setReceiveTimeout(5000);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> while(true){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> TextMessage message = (TextMessage) jmsTemplate.receive(destination);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> try {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> //这里还是同一个消费者</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> System.out.println("消费者 从目的地 " + destination.toString() + " 收到了消息" + message.getText());</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> } catch (JMSException e) {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> e.printStackTrace();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">}</span></p> </blockquote> <p><br></p> <p><strong><span style="color: rgb(123, 12, 0);">生产者</span></strong></p> <p><br></p> <p>直接在 main 方法中获取 ApplicationContext 运行,便于测试。</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">@Component</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">public class MsgProducer {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> @Autowired</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> private ProducerService producerService;</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public void send(){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> System.out.println("生产者开始发送消息:");</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> for(int i = 1; i < 11; i++){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> String msg = "生产者发出的消息";</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> producerService.sendMessageDefault(msg + "-----" + i);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public static void main(String[] args) {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> MsgProducer msgProducer = context.getBean(MsgProducer.class);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> msgProducer.send();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">}</span></p> </blockquote> <p><br></p> <p><strong><span style="color: rgb(123, 12, 0);">消费者</span></strong></p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">@Component</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">public class MsgConsumer {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> @Autowired</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> private ConsumerService consumerService;</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public void recive(){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> System.out.println("消费者 1 开始接收消息:");</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> consumerService.reciveDefault();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public static void main(String[] args) {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/applicationContext.xml");</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> MsgConsumer msgConsumer = context.getBean(MsgConsumer.class);</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> msgConsumer.recive();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">}</span></p> </blockquote> <p><br></p> <p>接下来就可以启动项目。同样是使用两种方式测试。</p> <p><br></p> <p><strong><span style="color: rgb(123, 12, 0);">第一种方式————点对点(Queue)</span></strong></p> <p><br></p> <p><strong>同步的方式</strong></p> <p><br></p> <p>先启动生产者发送10条消息, 再启动消费者,可以看到控制台显示成功收到10条消息。</p> <p><br></p> <p style="border-width: 0px;border-style: initial;border-color: initial;margin-bottom: 20px;font-size: 14px;font-family: "Microsoft YaHei", 宋体, "Myriad Pro", Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;white-space: normal;background-color: rgb(255, 255, 255);"><img class="aligncenter size-full wp-image-30160" data-ratio="0.7857878475798146" src="/upload/4b014ea958676fdad103b548a985d570.png" data-type="png" data-w="971" style="border-width: 0px;border-style: initial;border-color: initial;font-size: 0px;color: transparent;vertical-align: middle;text-align: center;margin: 0px;top: 0px;left: 0px;right: 0px;bottom: 0px;" title="点对点生产"></p> <p style="border-width: 0px;border-style: initial;border-color: initial;margin-bottom: 20px;font-size: 14px;font-family: "Microsoft YaHei", 宋体, "Myriad Pro", Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;white-space: normal;background-color: rgb(255, 255, 255);"><img class="aligncenter size-full wp-image-30161" data-ratio="0.7857878475798146" src="/upload/4b014ea958676fdad103b548a985d570.png" data-type="png" data-w="971" style="border-width: 0px;border-style: initial;border-color: initial;font-size: 0px;color: transparent;vertical-align: middle;text-align: center;margin: 0px;top: 0px;left: 0px;right: 0px;bottom: 0px;" title="点对点消费"></p> <p><strong>异步监听的方式</strong></p> <p><br></p> <p>通过监听器即可实现异步接收消息的效果,而不是像上面使用 while() 轮询同步的方式。</p> <p>项目中一般都是使用异步监听的方式,在 A 服务中发送了一条消息,B 服务可以利用消息监听器监听,当收到消息后,进行相应的操作。</p> <p><br></p> <p><strong>消息监听器(3种)</strong></p> <p><br></p> <p>通过继承 JMS 中的 MessageListener 接口,实现 onMessage() 方法,就可以自定义监听器。这是最基本的监听器。(可根据业务实现自定义的功能)</p> <p><br></p> <p>另外spring也给我们提供了其他类型的消息监听器,比如 SessionAwareMessageListener,它的作用不仅可以接收消息,还可以发送一条消息通知对方表示自己收到了消息。(还有一种是 MessageListenerAdapter)</p> <p><br></p> <p>一个简单的自定义监听器如下:收到消息后打印消息</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">public class QueueMessageListener implements MessageListener {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> public void onMessage(Message message) {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> //如果有消息</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> TextMessage tmessage = (TextMessage) message;</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> try {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> if(tmessage != null){</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> System.out.println("监听器监听消息:"+tmessage.getText());</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> } catch (JMSException e) {</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> e.printStackTrace();</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> }</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);">}</span></p> </blockquote> <p><br></p> <p>在 ActiveMQ.xml 中引入消息监听器:</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- 配置消息队列监听者(Queue) --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <bean id="queueMessageListener" class="com.service.QueueMessageListener" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!-- 显示注入消息监听容器,配置连接工厂,监听的目标是QueueDestination 或 topicDestination,监听器是上面自定义的监听器 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <bean id="queueListenerContainer"</span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> class="org.springframework.jms.listener.DefaultMessageListenerContainer"></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="connectionFactory" ref="connectionFactory" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="destination" ref="QueueDestination" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <!--<property name="destination" ref="topicDestination" />--></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> <property name="messageListener" ref="queueMessageListener" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"> </bean></span></p> </blockquote> <p><br></p> <p>可以看到,当使用消息监听器之后,每发送一条消息立马就会被监听到:</p> <p><br></p> <p style="text-align: center;"><img class="aligncenter size-full wp-image-30162" data-ratio="0.7857878475798146" src="/upload/4b014ea958676fdad103b548a985d570.png" data-type="png" data-w="971" style="border-width: 0px;border-style: initial;border-color: initial;font-size: 0px;color: transparent;vertical-align: middle;text-align: center;margin: 0px;top: 0px;left: 0px;right: 0px;bottom: 0px;" title="点对点监听器"></p> <p><br></p> <p><strong><span style="color: rgb(123, 12, 0);">第二种方式————发布/订阅(Topic)</span></strong></p> <p><br></p> <p><strong>同步的方式</strong></p> <p><br></p> <p>类似点对点中同步的方式,只是每个消费者都能收到生产者发出的全部消息,不再赘述。</p> <p><br></p> <p><strong>异步监听的方式</strong></p> <p><br></p> <p>启动两个监听器(两个消费者),对消息进行异步监听。看是否各自能收到生产者发送的消息。</p> <p><br></p> <blockquote> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><!-- 配置两个监听器 --></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><bean id="messageListener" class="com.service.TopicMessageListener" /></span></p> <p><span style="font-size: 12px;color: rgb(136, 136, 136);"><bean id="messageListener2" class="com.service.TopicMessageListener2" /></span></p> </blockquote> <p><br></p> <p style="text-align: center;"><img class="aligncenter size-full wp-image-30163" data-ratio="0.7857878475798146" src="/upload/4b014ea958676fdad103b548a985d570.png" data-type="png" data-w="971" style="border-width: 0px;border-style: initial;border-color: initial;font-size: 0px;color: transparent;vertical-align: middle;text-align: center;margin: 0px;top: 0px;left: 0px;right: 0px;bottom: 0px;" title="两个监听器"></p> <p><br></p> <p>可以看到,每个监听器各自都收到了生产者发送的10条消息。</p> <p><br></p> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);overflow-wrap: break-word !important;"> <section class="" style="margin-top: 10px;margin-bottom: 10px;max-width: 100%;box-sizing: border-box;text-align: left;overflow-wrap: break-word !important;"> <section class="" style="padding: 10px;max-width: 100%;box-sizing: border-box;display: inline-block;width: 668px;border-width: 1px;border-style: solid;border-color: rgb(226, 226, 226);box-shadow: rgb(226, 226, 226) 0px 16px 1px -13px;overflow-wrap: break-word !important;"> <section class="" powered-by="xiumi.us" style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section class="" style="max-width: 100%;box-sizing: border-box;overflow-wrap: break-word !important;"> <section class="" style="max-width: 100%;box-sizing: border-box;color: rgb(93, 93, 93);overflow-wrap: break-word !important;"> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;">【关于投稿】</p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;">如果大家有原创好文投稿,请直接给公号发送留言。</p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p class="" style="max-width: 100%;box-sizing: border-box;min-height: 1em;font-size: 13px;overflow-wrap: break-word !important;"><span style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">① 留言格式:</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">【投稿】+《 文章标题》+ 文章链接</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">② 示例:</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">【投稿】《不要自称是程序员,我十多年的 IT 职场总结》:http://blog.jobbole.com/94148/</span><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(53, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;">③ 最后请附上您的个人简介哈~</span></span></p> <p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> </section> </section> </section> </section> </section> </section> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;text-align: justify;white-space: normal;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: 14px;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">看完本文有收获?请转发分享给更多人</span></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;color: rgb(255, 169, 0);box-sizing: border-box !important;overflow-wrap: break-word !important;">关注「ImportNew」,提升Java技能</strong></p> <p style="max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 17px;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img class="" data-ratio="0.9166666666666666" data-s="300,640" data-type="png" data-w="600" width="auto" src="/upload/899866149276fa5fddb73c61ae04be64.png" style="box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 600px !important;"></p>
作者:不要哭啦
``` package cn.studyjava.util; /** * @author zsljava@163.com * JavaScript整数最大支持53位 * 时间41位 机器号1位 毫秒ID自增6位 一共48位 */ public class IdWorker { /** * 2016-01-01 00:00:00 */ private final static long twepoch = 1451577600000L; /** * 机器标识位数 */ private final static long workerIdBits = 1L; /** * 机器ID支持机器节点数0~1 */ public final static long maxWorkerId = ~(-1L << workerIdBits); /** * 毫秒内自增位 */ private final static long sequenceBits = 6L; /** * 毫秒内sequence范围0~63 */ public final static long sequenceMask = ~(-1L << sequenceBits); /** * 机器ID偏左移6位 */ private final static long workerIdShift = sequenceBits; /** * 时间毫秒左移7位 */ private final static long timestampLeftShift = sequenceBits + workerIdBits; private final long workerId; private long sequence = 0L; private long lastTimestamp = -1L; public IdWorker(final long workerId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } this.workerId = workerId; } public synchronized long nextId() { long timestamp = this.timeGen(); if (timestamp < this.lastTimestamp) { throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", this.lastTimestamp - timestamp)); } if (this.lastTimestamp == timestamp) { this.sequence = (this.sequence + 1) & sequenceMask; if (this.sequence == 0) { timestamp = this.tilNextMillis(this.lastTimestamp); } } else { this.sequence = 0; } this.lastTimestamp = timestamp; return ((timestamp - twepoch << timestampLeftShift)) | (this.workerId << workerIdShift) | (this.sequence); } private long tilNextMillis(final long lastTimestamp) { long timestamp = this.timeGen(); while (timestamp <= lastTimestamp) { timestamp = this.timeGen(); } return timestamp; } private long timeGen() { return System.currentTimeMillis(); } } ```
作者:微信小助手
<p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);text-align: center;"><span style="font-family: 微软雅黑;font-size: 14px;widows: 1;max-width: 100%;color: rgb(178, 178, 178);line-height: 34.1333px;letter-spacing: 0.8px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;">点击上方“</span><span style="font-family: 微软雅黑;font-size: 14px;widows: 1;max-width: 100%;line-height: 34.1333px;letter-spacing: 0.8px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(0, 122, 170);"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">程序员大咖</strong></span><span style="max-width: 100%;color: rgb(178, 178, 178);">”,选择“置顶公众号”</span></span><span style="font-family: 微软雅黑;widows: 1;max-width: 100%;font-size: 14px;color: rgb(178, 178, 178);line-height: 34.1333px;letter-spacing: 0.8px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"></span></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);text-align: center;"><span style="color: rgb(178, 178, 178);font-family: 微软雅黑;font-size: 18px;">关键时刻,第一时间送达!</span><img class="" data-ratio="0.0625" src="/upload/21f429670ba6010be4e5057a15790a6b.null" data-w="640" width="auto" style="font-family: 微软雅黑;font-size: 18px;color: rgb(178, 178, 178);box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;visibility: visible !important;width: 656px !important;"><a href="https://mp.weixin.qq.com/s?__biz=MzI4MDYwMDc3MQ==&mid=2247484909&idx=2&sn=b6319708cc2ed28833109f2434d3d043&scene=21#wechat_redirect" target="_blank"><span class="js_jump_icon h5_image_link" data-positionback="static" style="top: auto;left: auto;right: auto;bottom: auto;"><img class="" data-copyright="0" data-ratio="0.5128205128205128" src="/upload/8f1fa0ea66334dac238224f74f6f0ced.gif" data-type="gif" data-w="390" style="color: rgb(136, 136, 136);font-size: 14px;width: 526.193px;top: auto;left: auto;right: auto;bottom: auto;"></span></a></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(62, 62, 62);text-align: center;"><br></p> <section class="mpa-template" data-mpa-template-id="328323" data-mpa-color="null" data-mpa-category="fav" style="white-space: normal;"> <section class="mpa-template" data-mpa-template-id="328323" data-mpa-color="null" data-mpa-category="fav"> <blockquote> <p><span style="color: rgb(136, 136, 136);font-size: 10px;">来源:Java联盟</span></p> <p><span style="color: rgb(136, 136, 136);font-size: 10px;">https://mp.weixin.qq.com/s/kSoFRSbVHg3oRtPQ2Xezag</span></p> </blockquote> <blockquote> <p><span style="color: rgb(136, 136, 136);font-size: 10px;">程序员大咖整理发布,转载请联系作者获得授权</span></p> </blockquote> <p><span style="color: rgb(136, 136, 136);font-size: 10px;"><br></span></p> </section> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">查询操作</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">在实际的项目中使用的次数是最多的</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">所以我们单独拿出来写~</span></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="899481" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 10px 15px;max-width: 100%;font-weight: bold;color: rgb(110, 156, 40);border-radius: 45%;text-align: center;background-color: rgb(229, 243, 208);letter-spacing: 0.5px;line-height: 1.75em;">查询操作</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">先来创建一个用户表,作为我们练习查询操作的对象,当然这个表和实际项目中的表还是有一定的区别的~小伙伴们不要介意哈~</span><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">创建用户表:</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">在这张表中我们设置了三个字段,分别是主键uid,用户名uname,和用户的存款umoney~</span><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.9049586776859504" data-s="300,640" src="/upload/1b71be16fa56ba864da2cd00b12cf9cf.png" data-type="png" data-w="242"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(136, 136, 136);">下面就可以进行查询操作了</span></p> <p><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">简单查询:</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">查询所有信息</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select * from 表名</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.8921161825726142" data-s="300,640" src="/upload/605334b58a945381cad5e0184c28f78f.png" data-type="png" data-w="241"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">注意:</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">在实际项目开发中,不推荐使用此种查询方式。因为要查询的字段信息不明确,若是字段数量很多,会导致查询速度很慢。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">查询指定字段信息</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select 字段1,字段2,...from 表名;</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.8616600790513834" data-s="300,640" src="/upload/d855dbd4364dae8fc56631b02913fd47.png" data-type="png" data-w="253"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">别名查询</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">使用的as关键字,as可以省略的.</span><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">别名可以给表中的字段,表设置别名。 当查询语句复杂时,使用别名可以极大的简便操作。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">1)表别名格式:</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select * from 表名 as 别名;</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.8326848249027238" data-s="300,640" src="/upload/deaafaca538f618998365a573978eec4.png" data-type="png" data-w="257"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;"><br></span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">或者把as省略</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select * from 表名 别名;</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.9159663865546218" data-s="300,640" src="/upload/a1cf9948805e4ad938f2458950ccc2af.png" data-type="png" data-w="238"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">列别名格式:</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select 字段名 as 别名 from 表名;</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.7743055555555556" data-s="300,640" src="/upload/65881727da044433f33ef119b19c64a2.png" data-type="png" data-w="288" style="width: 236.776px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">或者把as省略</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select 字段名 别名 from 表名;</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.8620689655172413" data-s="300,640" src="/upload/a9dfd148858758564a4ec46635be29d5.png" data-type="png" data-w="261"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">去重查询</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">先在表中添加一些重复的数据~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.8587360594795539" data-s="300,640" src="/upload/c9b0b38e90c8519e7adbf7f9c2855422.png" data-type="png" data-w="269"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">distinct用于去除重复记录</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select distinct 字段 from 表名;</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.6390532544378699" data-s="300,640" src="/upload/1b12769555a3034c500a122aa20cd09.png" data-type="png" data-w="338"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(136, 136, 136);"> 一共8条数据</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(136, 136, 136);">去重之后就剩下7条数据了~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">我们在sql语句的操作中,可以<strong>直接对列进行运算。</strong>将所有存款金额+100元进行显示。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select uname,umoney+100 from user;</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.7355623100303952" data-s="300,640" src="/upload/b4f21772ff31ffad60b43af808110f67.png" data-type="png" data-w="329"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">条件查询</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">在查询的时候,我们可以设定一些条件来筛选我们查询的内容~</span><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">where后的条件的写法:</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 14px;">1)>(大于)、>=(大于等于)、<(小于)、<=(小于等于)、=(等于)、><(不等于)。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 14px;">2)between..and..(在某一区间)、in(set)(在in列表中的值)、like‘%%’,模糊查询,%代表一个或多个任意字符、is null 判断为空。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 14px;">3)and(与、多个条件同时成立)、or(或、多个条件中任意一个条件成立)、not(非、不成立)。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">下面我们来练习一下~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">1)查询名字是“张三”的人的信息。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.3225806451612903" data-s="300,640" src="/upload/81dd1673f603a16b231e78eaa39dc021.png" data-type="png" data-w="372" style="width: 315.71px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">2)查询存款 >100 的所有人的信息。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.45325779036827196" data-s="300,640" src="/upload/eb6cdf80f91446fb3a583452895ba209.png" data-type="png" data-w="353" style="width: 289.403px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">3)查询名字中带“三”的人的信息。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.29975429975429974" data-s="300,640" src="/upload/93404ed05660d348dc946ed406c93c7.png" data-type="png" data-w="407" style="width: 342.017px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">4)查询id在(2,5,8)范围内的信息。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.416" data-s="300,640" src="/upload/897b460ab531945fbfc156799f9fcc85.png" data-type="png" data-w="375"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">5)查询id为3、6或者9的人的信息</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.30472103004291845" data-s="300,640" src="/upload/b9421d10acaeced36bc303fc32c92d9.png" data-type="png" data-w="466" style="width: 394.645px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 14px;color: rgb(136, 136, 136);">剩下的小伙伴们自己练习一下吧~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">排序查询</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">在数据库的查询操作中还有排序的操作~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">语法:</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">select ... order by 字段1 asc|desc,字段2 asc|desc</span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;"><strong>asc 为升序</strong></span></strong></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.6153846153846154" data-s="300,640" src="/upload/392d42bd6af31767350646795027d771.png" data-type="png" data-w="377"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;"><strong>desc 为降序</strong></span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.5912596401028277" data-s="300,640" src="/upload/f7f498ead708e239c65af83e12541186.png" data-type="png" data-w="389" style="width: 368.324px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">这个的操作的作用相信小伙伴们应该有所了解吧~像我们逛淘宝的时候,有时候就会筛选一下商品的销量和价格排序~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">聚合函数</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">常用的聚合函数:</span><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><strong><span style="font-size: 15px;">sum()求和,avg()求平均值,max()求最大值,min()求最小值,count()统计数量;</span></strong><span style="font-size: 15px;">注意:</span><span style="font-size: 15px;">聚合函数不统计 null 值。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;"><br></span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">1)获取所有人的存款的总数。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.4479166666666667" data-s="300,640" src="/upload/3eb85a033d8dc57f98310844d1666ea5.png" data-type="png" data-w="288"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">2)获取所有人的存款的平均数。</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.41638225255972694" data-s="300,640" src="/upload/8ef41491c855ed2aad023f21bcdcdc88.png" data-type="png" data-w="293"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">3)获取一共有多少人</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.4485294117647059" data-s="300,640" src="/upload/f5a8731e053d6c6f0900116331d6b32.png" data-type="png" data-w="272"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <section class="xmt-style-block" data-style-type="5" data-tools="新媒体排版" data-id="879095" style="padding-right: 1em;padding-left: 1em;white-space: normal;"> <p style="margin-top: 10px;margin-bottom: 10px;padding: 5px 10px;border-left: 5px solid rgb(102, 103, 101);font-size: 16px;font-weight: bold;color: rgb(102, 102, 102);letter-spacing: 0.5px;line-height: 1.75em;">分组查询</p> </section> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">首先添加一个分组id,</span><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.1685082872928177" data-s="300,640" src="/upload/1ebb62ea9dd6a977c07ff8922b31e135.png" data-type="png" data-w="362"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">然后把数据分成两组~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.28794642857142855" data-s="300,640" src="/upload/a8e273577e053cf149f15b279324f143.png" data-type="png" data-w="448" style="width: 368.324px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">查看一下表中的信息:</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.7451612903225806" data-s="300,640" src="/upload/e1c3e4dc8dcaee5bc4ffa9fde87a13b7.png" data-type="png" data-w="310"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">现在根据cid字段的分组情况,统计一下各个分组中的成员的个数~</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.3469879518072289" data-s="300,640" src="/upload/bca62d0dd013d502145f4ef106552e44.png" data-type="png" data-w="415" style="width: 368.324px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;text-align: center;"><br></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">再根据cid分组,统计出分组中的平均存款数大于10000的那组,</span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;text-align: center;letter-spacing: 0.5px;line-height: 1.75em;"><img class="" data-ratio="0.2" data-s="300,640" src="/upload/ef3254f845f4edceb5833ec3ddb2e02f.png" data-type="png" data-w="635" style="width: 394.645px;"></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;"><br></span></p> <p style="padding-right: 1em;padding-left: 1em;white-space: normal;letter-spacing: 0.5px;line-height: 1.75em;"><span style="font-size: 15px;">注意:分组后的条件查询要用having~</span></p> <p style="white-space: normal;"> <mp-miniprogram class="miniprogram_element" data-miniprogram-appid="wx589a25442dd42e09" data-miniprogram-path="pages/home/dashboard/index" data-miniprogram-nickname="程序员商城" data-miniprogram-avatar="http://mmbiz.qpic.cn/mmbiz_png/ttVBIFTFEYn54Qop5RzLtdy3gzXuWzzpcAzfQ7oM4voOQt0qZFnibwcVQFHxfjqicLgeicN3pofSE4Gjhf41y9ETQ/0?wx_fmt=png" data-miniprogram-title="每日秒杀,数量有限,先到先得" data-miniprogram-imageurl="http://mmbiz.qpic.cn/mmbiz_jpg/2LJz3aY3IVgQWkr7Iwshn5aC0OtFZ3gczwpNJxW9uHBJ2SUsWmbMvbIVEo92pL1Z8KdDqyHyfozXK8xy2Sice2g/0?wx_fmt=jpeg"></mp-miniprogram></p> <p style="white-space: normal;"><a href="https://mp.weixin.qq.com/s?__biz=MzA3NzM0NzkxMQ==&mid=2655359779&idx=2&sn=b40fd81111b7ea799b6788074b24aab9&scene=21#wechat_redirect" target="_blank"><span class="js_jump_icon h5_image_link" data-positionback="static" style="top: auto;left: auto;right: auto;bottom: auto;"><img class="" data-copyright="0" data-ratio="0.38" src="/upload/f86af06b0dbd217c69f04859cbb0f24c.gif" data-type="gif" data-w="550"></span></a><strong style="font-size: 16px;font-family: 微软雅黑;letter-spacing: 1px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><a href="https://mp.weixin.qq.com/s?__biz=MzI0NjYxMDQ4OQ==&mid=2247484655&idx=4&sn=b63f0a1e32df2fed7ba7e0f0e838e3f9&scene=21#wechat_redirect" target="_blank"><span style="max-width: 100%;color: rgb(67, 149, 245);outline: none 0px;line-height: normal;text-indent: 2em;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"></span><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(67, 149, 245);outline: none 0px;line-height: normal;text-indent: 2em;top: auto;left: auto;right: auto;bottom: auto;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;"><span class="js_jump_icon h5_image_link" data-positionback="static" style="top: auto;left: auto;right: auto;bottom: auto;"><img class="__bg_gif" data-ratio="0.48936170212765956" src="/upload/6f7a0016c2a7d885c35da32a06291359.null" data-type="gif" data-w="47" width="auto" style="border-width: 0px;border-style: initial;border-color: initial;line-height: 38.4384px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: auto !important;"></span></span><span style="max-width: 100%;color: rgb(255, 41, 65);outline: none 0px;font-size: 20px;box-sizing: border-box !important;word-wrap: break-word !important;overflow-wrap: break-word !important;">【点击成为源码大神】</span></strong></strong></a></strong></strong></p> <p style="white-space: normal;"><strong style="font-size: 16px;font-family: 微软雅黑;letter-spacing: 1px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><br></strong></strong></p> <p style="white-space: normal;"><strong style="font-size: 16px;font-family: 微软雅黑;letter-spacing: 1px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="color: rgb(51, 51, 51);max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">▼点击「</strong></strong><span style="color: rgb(234, 34, 0);"><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">阅读原文</strong></strong></span><strong style="max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;"><strong style="outline: 0px;max-width: 100%;box-sizing: border-box !important;word-wrap: break-word !important;">」进入程序员商城</strong></strong></strong></strong></strong></strong></p>
作者:じ☆ve宝贝
1.下载Postman 2.找到Postman_v4.1.3.crx,将后缀改为.zip或者.rar 3.解压到一个目录中 4.在chrome地址栏中输入chrome://extensions/ 5.  打开目录后选择刚才解压的目录,如果提示有错误(打开目录将_metadata修改为metadata重试即可) 6.
作者:微信小助手
<p style="white-space: normal;max-width: 100%;min-height: 1em;color: rgb(51, 51, 51);text-align: center;"><span class="" style="orphans: 2;widows: 2;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;max-width: 100%;white-space: pre-wrap;font-size: 14px;color: rgb(255, 41, 65);line-height: 22.4px;box-sizing: border-box !important;overflow-wrap: break-word !important;">(给</span><span style="orphans: 2;widows: 2;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;max-width: 100%;white-space: pre-wrap;font-size: 14px;line-height: 22.4px;color: rgb(0, 128, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;">前端大全</span><span class="" style="orphans: 2;widows: 2;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;max-width: 100%;white-space: pre-wrap;font-size: 14px;color: rgb(255, 41, 65);line-height: 22.4px;box-sizing: border-box !important;overflow-wrap: break-word !important;">加星标,提升前端技能</span><span class="" style="orphans: 2;widows: 2;font-family: -apple-system-font, system-ui, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;max-width: 100%;white-space: pre-wrap;color: rgb(255, 41, 65);font-size: 14px;line-height: 22.4px;box-sizing: border-box !important;overflow-wrap: break-word !important;">)</span></p> <blockquote style="white-space: normal;font-variant-ligatures: normal;orphans: 2;widows: 2;"> <p><span style="font-size: 14px;">英文:Alex 译文:zhangbao90s</span></p> <p><span style="font-size: 14px;">https://juejin.im/post/5d906269f265da5ba7451b02</span></p> </blockquote> <p style="white-space: normal;font-variant-ligatures: normal;orphans: 2;widows: 2;"><span style="font-size: 15px;"></span></p> <h2 class="" data-id="heading-0" style="margin-top: 35px;margin-bottom: 10px;padding-bottom: 12px;font-size: 24px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;line-height: 1.5;border-bottom: 1px solid rgb(236, 236, 236);font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 15px;">概述</span></strong></h2> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">前端开发中,经常会遇到发送异步请求的场景。</span><span style="font-size: 15px;">一个功能齐全的 HTTP 请求库可以大大降低我们的开发成本,提高开发效率。</span></p> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">axios 就是这样一个 HTTP 请求库,近年来非常热门。</span><span style="font-size: 15px;">目前,它在 GitHub 上拥有超过 40,000 的 Star,许多权威人士都推荐使用它。</span></p> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">因此,我们有必要了解下 axios 是如何设计,以及如何实现 HTTP 请求库封装的。</span><span style="font-size: 15px;">撰写本文时,axios 当前版本为 0.18.0,我们以该版本为例,来阅读和分析部分核心源代码。</span><span style="font-size: 15px;">axios 的所有源文件都位于 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">lib</span></code><span style="font-size: 15px;"> 文件夹中,下文中提到的路径都是相对于 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">lib</span></code><span style="font-size: 15px;"> 来说的。</span></p> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">本文我们主要讨论:</span></p> <ul class=" list-paddingleft-2" style=""> <li><p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">怎样使用 axios。</span></p></li> <li><p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">axios 的核心模块(请求、拦截器、撤销)是如何设计和实现的?</span></p></li> <li><p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">axios 的设计优点是什么?</span></p></li> </ul> <h2 class="" data-id="heading-1" style="margin-top: 35px;margin-bottom: 10px;padding-bottom: 12px;font-size: 24px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;line-height: 1.5;border-bottom: 1px solid rgb(236, 236, 236);font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 15px;">如何使用 axios</span></strong></h2> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">要理解 axios 的设计,首先需要看一下如何使用 axios。</span><span style="font-size: 15px;">我们举一个简单的例子来说明下 axios API 的使用。</span></p> <h3 class="" data-id="heading-2" style="margin-top: 35px;margin-bottom: 10px;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;line-height: 1.5;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">发送请求</span></h3> <pre style="max-width: 100%;letter-spacing: 0.544px;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 15px;line-height: 1.75;overflow: auto;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code class="" lang="javascript" style="padding: 18px 15px 12px;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">axios({</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">method</span>:<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'get'</span>,</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">url</span>:<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'http://bit.ly/2mTM3nY'</span>,</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">responseType</span>:<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'stream'</span></span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">})</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> .then(<span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;">function</span>(<span class="" style="font-size: 12px;max-width: 100%;">response</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> response.data.pipe(fs.createWriteStream(<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'ada_lovelace.jpg'</span>))</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">});</span><span style="max-width: 100%;top: 6px;right: 15px;line-height: 1;cursor: pointer;color: rgba(140, 140, 140, 0.8);transition: color 0.1s ease 0s;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></code></pre> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">这是一个官方示例。</span><span style="font-size: 15px;">从上面的代码中可以看到,axios 的用法与 jQuery 的 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">ajax</span></code><span style="font-size: 15px;"> 方法非常类似,两者都返回一个 Promise 对象(在这里也可以使用成功回调函数,但还是更推荐使用 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">Promise</span></code><span style="font-size: 15px;"> 或 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">await</span></code><span style="font-size: 15px;">),然后再进行后续操作。</span></p> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">这个实例很简单,不需要我解释了。</span><span style="font-size: 15px;">我们再来看看如何添加一个拦截器函数。</span></p> <h3 class="" data-id="heading-3" style="margin-top: 35px;margin-bottom: 10px;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;line-height: 1.5;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">添加拦截器函数</span></h3> <pre style="max-width: 100%;letter-spacing: 0.544px;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 15px;line-height: 1.75;overflow: auto;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code class="" lang="javascript" style="padding: 18px 15px 12px;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">axios.interceptors.request.use(<span class="" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="max-width: 100%;font-weight: 700;">function</span> (<span class="" style="max-width: 100%;">config</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span> config;</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> }, <span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;">function</span> (<span class="" style="font-size: 12px;max-width: 100%;">error</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span> <span class="" style="font-size: 12px;max-width: 100%;color: rgb(0, 134, 179);box-sizing: border-box !important;overflow-wrap: break-word !important;">Promise</span>.reject(error);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> });</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">axios.interceptors.response.use(<span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;">function</span> (<span class="" style="font-size: 12px;max-width: 100%;">response</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span> response;</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> }, <span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;">function</span> (<span class="" style="font-size: 12px;max-width: 100%;">error</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span> <span class="" style="font-size: 12px;max-width: 100%;color: rgb(0, 134, 179);box-sizing: border-box !important;overflow-wrap: break-word !important;">Promise</span>.reject(error);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> });</span><span style="max-width: 100%;top: 6px;right: 15px;line-height: 1;cursor: pointer;color: rgba(140, 140, 140, 0.8);transition: color 0.1s ease 0s;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></code></pre> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">从上面的代码,我们可以知道:</span><span style="font-size: 15px;">发送请求之前,我们可以对请求的配置参数(</span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">config</span></code><span style="font-size: 15px;">)做处理;</span><span style="font-size: 15px;">在请求得到响应之后,我们可以对返回数据做处理。</span><span style="font-size: 15px;">当请求或响应失败时,我们还能指定对应的错误处理函数。</span></p> <h3 class="" data-id="heading-4" style="margin-top: 35px;margin-bottom: 10px;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;line-height: 1.5;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">撤销 HTTP 请求</span></h3> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">在开发与搜索相关的模块时,我们经常要频繁地发送数据查询请求。</span><span style="font-size: 15px;">一般来说,当我们发送下一个请求时,需要撤销上个请求。</span><span style="font-size: 15px;">因此,能撤销相关请求功能非常有用。</span><span style="font-size: 15px;">axios 撤销请求的示例代码如下:</span></p> <pre style="max-width: 100%;letter-spacing: 0.544px;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 15px;line-height: 1.75;overflow: auto;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code class="" lang="javascript" style="padding: 18px 15px 12px;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"><span class="" style="max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">const</span> CancelToken = axios.CancelToken;</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">const</span> source = CancelToken.source();</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">axios.get(<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'/user/12345'</span>, {</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">cancelToken</span>: source.token</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">}).catch(<span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;">function</span>(<span class="" style="font-size: 12px;max-width: 100%;">thrown</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">if</span> (axios.isCancel(thrown)) {</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;color: rgb(0, 134, 179);box-sizing: border-box !important;overflow-wrap: break-word !important;">console</span>.log(<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'请求撤销了'</span>, thrown.message);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> } <span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">else</span> {</span> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> }</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">});</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">axios.post(<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'/user/12345'</span>, {</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">name</span>: <span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'新名字'</span></span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">}, {</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">cancelToken</span>: source.token</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">}).</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">source.cancel(<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'用户撤销了请求'</span>);</span><span style="max-width: 100%;top: 6px;right: 15px;line-height: 1;cursor: pointer;color: rgba(140, 140, 140, 0.8);transition: color 0.1s ease 0s;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></code></pre> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">从上例中可以看到,在 axios 中,使用基于 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">CancelToken</span></code><span style="font-size: 15px;"> 的撤销请求方案。</span><span style="font-size: 15px;">然而,该提案现已撤回,详情如 点这里。</span><span style="font-size: 15px;">具体的撤销请求的实现方法,将在后面的源代码分析的中解释。</span></p> <h2 class="" data-id="heading-5" style="margin-top: 35px;margin-bottom: 10px;padding-bottom: 12px;font-size: 24px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;line-height: 1.5;border-bottom: 1px solid rgb(236, 236, 236);font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong><span style="font-size: 15px;">axios 核心模块的设计和实现</span></strong></h2> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">通过上面的例子,我相信每个人都对 axios 的使用有一个大致的了解了。</span><span style="font-size: 15px;">下面,我们将根据模块分析 axios 的设计和实现。</span><span style="font-size: 15px;">下面的图片,是我在本文中会介绍到的源代码文件。</span><span style="font-size: 15px;">如果您感兴趣,最好在阅读时克隆相关的代码,这能加深你对相关模块的理解。</span></p> <figure style="margin: 22px auto;max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: center;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="" data-height="499" data-ratio="1.6633333333333333" data-type="other" data-w="300" data-width="300" src="/upload/2bbf41036e953066f760c0ec5582d158.other" style="border-style: none;max-height: none;background-color: transparent;background-position: 50% center;background-repeat: no-repeat;cursor: zoom-in;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: auto !important;"> </figure> <h3 class="" data-id="heading-6" style="margin-top: 35px;margin-bottom: 10px;font-size: 18px;max-width: 100%;letter-spacing: 0.544px;white-space: normal;line-height: 1.5;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">HTTP 请求模块</span></h3> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">请求模块的代码放在了 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">core/dispatchRequest.js</span></code><span style="font-size: 15px;"> 文件中,这里我只展示了一些关键代码来简单说明:</span></p> <pre style="max-width: 100%;letter-spacing: 0.544px;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 15px;line-height: 1.75;overflow: auto;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code class="" lang="javascript" style="padding: 18px 15px 12px;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"><span class="" style="max-width: 100%;color: rgb(0, 134, 179);box-sizing: border-box !important;overflow-wrap: break-word !important;">module</span>.exports = <span class="" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="max-width: 100%;font-weight: 700;">function</span> <span class="" style="max-width: 100%;color: rgb(153, 0, 0);font-weight: 700;">dispatchRequest</span>(<span class="" style="max-width: 100%;">config</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> throwIfCancellationRequested(config);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">var</span> adapter = config.adapter || defaults.adapter;</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span> adapter(config).then(<span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;">function</span> <span class="" style="font-size: 12px;max-width: 100%;color: rgb(153, 0, 0);font-weight: 700;">onAdapterResolution</span>(<span class="" style="font-size: 12px;max-width: 100%;">response</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> throwIfCancellationRequested(config);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span> response;</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> }, <span class="" style="font-size: 12px;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;">function</span> <span class="" style="font-size: 12px;max-width: 100%;color: rgb(153, 0, 0);font-weight: 700;">onAdapterRejection</span>(<span class="" style="font-size: 12px;max-width: 100%;">reason</span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">if</span> (!isCancel(reason)) {</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> throwIfCancellationRequested(config);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">return</span> <span class="" style="font-size: 12px;max-width: 100%;color: rgb(0, 134, 179);box-sizing: border-box !important;overflow-wrap: break-word !important;">Promise</span>.reject(reason);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> });</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;">};</span><span style="max-width: 100%;top: 6px;right: 15px;line-height: 1;cursor: pointer;color: rgba(140, 140, 140, 0.8);transition: color 0.1s ease 0s;font-size: 15px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><br></span></code></pre> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">上面的代码中,我们能够知道 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">dispatchRequest</span></code><span style="font-size: 15px;"> 方法是通过 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">config.adapter</span></code><span style="font-size: 15px;"> ,获得发送请求模块的。</span><span style="font-size: 15px;">我们还可以通过传递,符合规范的适配器函数来替代原来的模块(一般来说,我们不会这样做,但它是一个松散耦合的扩展点)。</span></p> <p style="margin-top: 22px;margin-bottom: 22px;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;white-space: normal;line-height: inherit;font-family: "PingFang SC", "Source Sans Pro", "Hiragino Sans GB", "Helvetica Neue", Helvetica, "Microsoft Yahei", arial, sans-serif;font-size: 15px;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">在 </span><code style="padding: 0.065em 0.4em;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 0.87em;word-break: break-word;color: rgb(255, 80, 44);background-color: rgb(255, 245, 245);border-radius: 2px;overflow-x: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 15px;">defaults.js</span></code><span style="font-size: 15px;"> 文件中,我们可以看到相关适配器的选择逻辑——根据当前容器的一些独特属性和构造函数,来确定使用哪个适配器。</span></p> <pre style="max-width: 100%;letter-spacing: 0.544px;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 15px;line-height: 1.75;overflow: auto;text-align: left;background-color: rgb(255, 255, 255);box-sizing: border-box !important;overflow-wrap: break-word !important;"><code class="" lang="javascript" style="padding: 18px 15px 12px;max-width: 100%;font-family: Menlo, Monaco, Consolas, "Courier New", monospace;font-size: 1rem;word-break: normal;background: rgb(248, 248, 248);border-radius: 2px;overflow-x: auto;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"><span class="" style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span class="" style="max-width: 100%;font-weight: 700;">function</span> <span class="" style="max-width: 100%;color: rgb(153, 0, 0);font-weight: 700;">getDefaultAdapter</span>(<span class="" style="max-width: 100%;"></span>) </span>{</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">var</span> adapter;</span> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="font-size: 12px;"><span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">if</span> (<span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">typeof</span> process !== <span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'undefined'</span> && <span class="" style="font-size: 12px;max-width: 100%;color: rgb(0, 134, 179);box-sizing: border-box !important;overflow-wrap: break-word !important;">Object</span>.prototype.toString.call(process) === <span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'[object process]'</span>) {</span> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> adapter = <span class="" style="font-size: 12px;max-width: 100%;color: rgb(0, 134, 179);box-sizing: border-box !important;overflow-wrap: break-word !important;">require</span>(<span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'./adapters/http'</span>);</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> } <span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">else</span> <span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">if</span> (<span class="" style="font-size: 12px;max-width: 100%;font-weight: 700;box-sizing: border-box !important;overflow-wrap: break-word !important;">typeof</span> XMLHttpRequest !== <span class="" style="font-size: 12px;max-width: 100%;color: rgb(221, 17, 68);box-sizing: border-box !important;overflow-wrap: break-word !important;">'undefined'</span>) {</span> <br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 12px;"> adapter = <span cla