作者:じ☆ve不哭
> tomcat http强制301永久跳转https。 全站启用http后经过检测跳转为302临时重定向。翻阅官方文档后发现需要增加transportGuaranteeRedirectStatus=301参数来制定。 下方配置文件中为tomcat http强制跳转https以及同一tomcat多https(域名)项目且不同证书的配置 ``` <?xml version="1.0" encoding="UTF-8"?> <Server port="8005" shutdown="SHUTDOWN"> <Listener className="org.apache.catalina.startup.VersionLoggerListener" /> <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /> <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <GlobalNamingResources> <Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" pathname="conf/tomcat-users.xml" /> </GlobalNamingResources> <Service name="Catalina"> <Connector port="80" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="443" /> <!-- 配置证书文件信息 --> <Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" sslProtocols="TLSv1.1+TLSv1.2"> <SSLHostConfig> <!--证书文件所在的目录 --> <Certificate certificateKeystoreFile="/data/keys/studyjava.cn.pfx" certificateKeystoreType="PKCS12" certificateKeystorePassword="studyjava" /> <!--配置类型 刚才password文件里面的密码 --> </SSLHostConfig> <SSLHostConfig hostName="weixin.studyjava.cn"> <!--证书文件所在的目录 --> <Certificate certificateKeystoreFile="/data/keys/weixin.studyjava.cn.pfx" certificateKeystoreType="PKCS12" certificateKeystorePassword="studyjava" /> <!--配置类型 刚才password文件里面的密码 --> </SSLHostConfig> </Connector> <!-- Define an AJP 1.3 Connector on port 8009 --> <Connector port="8009" protocol="AJP/1.3" redirectPort="443" /> <Engine name="Catalina" defaultHost="studyjava.cn"> <!-- tomcat永久配置302跳转 --> <!-- transportGuaranteeRedirectStatus=301必须要加,否则默认是302临时跳转 --> <Realm className="org.apache.catalina.realm.LockOutRealm" transportGuaranteeRedirectStatus="301"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> </Realm> <Host name="studyjava.cn" appBase="webapps" unpackWARs="true" autoDeploy="true"> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> <Host name="weixin.studyjava.cn" appBase="/tomcat/webapps/weixin" unpackWARs="true" autoDeploy="false"> <Alias>weixin.studyjava.cn</Alias> <Context path="" docBase="/tomcat/webapps/weixin" debug="0" reloadable="true"/> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> </Engine> </Service> </Server> ```
作者:微信小助手
<p style="text-align: left;" data-mpa-powered-by="yiban.io"><span style="color: rgb(2, 30, 170);font-size: 16px;">2017年,小灰曾经发布过一篇关于红黑树的漫画,当时由于时间仓促,部分知识点一带而过,并没有讲解得很细致全面。</span></p> <p style="text-align: left;"><span style="color: rgb(2, 30, 170);font-size: 16px;"><br></span></p> <p style="text-align: left;"><span style="color: rgb(2, 30, 170);font-size: 16px;">最近,小灰把这个知识点重新做了总结,分成上下两篇,希望大家把红黑树这个重要的数据结构彻底吃透。</span></p> <p style="text-align: left;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/d9ee06f7d41aef94a97d09618e67b844.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/96ca325b7aa38749e8c453b7c01d7048.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;white-space: normal;background-color: rgb(255, 255, 255);text-align: center;"><strong style="font-size: 18px;letter-spacing: 0.544px;">————— 第二天 —————</strong></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/7ec85b52ea96fc8b3a68f5aae96d1633.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/89393923dcb191c4445ca3d54155f7f1.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/46f3a2b394d0f98449ddfdd6e703e92f.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/adc314dd8a6bb43a0b9f7ce76976129e.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/2e65ee1c5de3f1cc541a572c0db7aa73.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/e13e8f108dcb575af8f9f53c2c904d9a.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/35cf8c8ed13e92a8dfbbec1ed30775cb.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="white-space: normal;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;"><span style="font-size: 18px;">————————————</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/df62500d0768bdde1d3b153375c3f8bb.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/9086f637e57afca2254297051394abe0.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/b56560822195496c66b9edb48169f386.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5533428165007113" data-s="300,640" src="/upload/9c7457304476263750a11a98be6820bf.png" data-type="png" data-w="703" style=""></p> <p style="text-align: center;"><br></p> <p><br></p> <p><span style="font-size: 18px;">二叉查找树(BST)具备什么特性呢?</span></p> <p><br></p> <p><span style="font-size: 18px;">1.<strong>左</strong>子树上所有结点的值均<strong>小于或等于</strong>它的根结点的值。</span></p> <p><span style="font-size: 18px;">2.<strong>右</strong>子树上所有结点的值均<strong>大于或等于</strong>它的根结点的值。</span></p> <p><span style="font-size: 18px;">3.左、右子树也分别为二叉排序树。</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><span style="font-size: 18px;">下图中这棵树,就是一颗典型的二叉查找树:</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5513748191027497" data-s="300,640" src="/upload/3b3148f6ae3d055949ea46f824d311a8.png" data-type="png" data-w="691" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5533428165007113" data-s="300,640" src="/upload/774bd9ecc02769f223eef373f0fd9525.png" data-type="png" data-w="703" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">1.查看根结点<strong>9</strong>:</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5513748191027497" data-s="300,640" src="/upload/ad22cd8ef635da54b1307ec1ff87cd5e.png" data-type="png" data-w="691" style=""></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span><br></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">2.根据二叉查找树左子树小、右子树大的特性,<strong>10 > 9</strong>,因此值为10的结点只可能在根结点的右子树当中,我们查看右孩子结点<strong>13</strong>:</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5513748191027497" data-s="300,640" src="/upload/f94da7b4ff544d95adf1de0170dc3d81.png" data-type="png" data-w="691" style=""></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span><br></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">3.由于<strong>10 < 13</strong>,因此查看左孩子<strong style="font-size: 18px;white-space: normal;">11</strong>:</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5513748191027497" data-s="300,640" src="/upload/5697e222cf84e274db86c8768d43bd7f.png" data-type="png" data-w="691" style=""></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span><br></p> <p style="text-align: center;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">4.由于<strong>10 < 11</strong>,因此查看左孩子<strong style="font-size: 18px;white-space: normal;">10</strong>,发现10正是要查找的结点:</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5513748191027497" data-s="300,640" src="/upload/4ec0b4ab8f347e152fb49750cf65bfe0.png" data-type="png" data-w="691" style=""></p> <p><img class="rich_pages" data-ratio="0.5533428165007113" data-s="300,640" src="/upload/85bfdb92599614cf33d43eb1f3c88a01.png" data-type="png" data-w="703" style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5533428165007113" data-s="300,640" src="/upload/9d9102a3cc36bdf6972410ff0bd48181.png" data-type="png" data-w="703" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5533428165007113" data-s="300,640" src="/upload/59851d71572a08281d18864aee56de51.png" data-type="png" data-w="703" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/b3b71e5177679e39336904dd2479a905.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/39e34ed622be61b545cd38fdf886dacd.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/62910f7e03cb03ac6d50928909120d00.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/3d7edfd21d8fb65bae25a8cae6a9fa0.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">假设初始的二叉查找树只有三个结点,根结点值为9,左孩子值为8,右孩子值为12:</span></p> <p style="text-align: left;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.4745308310991957" data-s="300,640" src="/upload/c1a7f88c84473c4006dd0c5db77a87ad.png" data-type="png" data-w="373" style=""></p> <p><br></p> <p><span style="font-size: 18px;">接下来我们依次插入如下五个结点:7,6,5,4,3。依照二叉查找树的特性,结果会变成什么样呢?</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.1368613138686132" data-s="300,640" src="/upload/7d40795b7c2729765ba0e1099c1c761a.png" data-type="png" data-w="548" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/81d4ffc80533c9f026d983132683721e.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/e7feb2a48fdde95219913833e4fb9b17.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/5e987aec1788993ec473b09174519525.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/460edfb4dc84e8ef2bdc3fa8f45a31d7.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p><span style="font-size: 18px;">1.结点是红色或黑色。</span></p> <p><span style="font-size: 18px;">2.根结点是黑色。</span></p> <p><span style="font-size: 18px;">3.每个叶子结点都是黑色的空结点(NIL结点)。</span></p> <p><span style="font-size: 18px;">4 每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)</span></p> <p><span style="font-size: 18px;">5.从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。</span></p> <p><br></p> <p><span style="font-size: 18px;">下图中这棵树,就是一颗典型的红黑树:</span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5714285714285714" data-s="300,640" src="/upload/109179a40577532f56fffdfcccdd7a0c.png" data-type="png" data-w="812" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/7cc42b88bfb273e091d73d1ccc4e0e38.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/16b17591f4627ccf2dad4626ddae9453.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/81e0f1a9a76dcebce3a33ee1a1fe86ba.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">什么情况下会破坏红黑树的规则,什么情况下不会破坏规则呢?我们举两个简单的例子:</span></p> <p><br></p> <p><span style="font-size: 18px;">1.向原红黑树插入值为<strong>14</strong>的新结点:</span></p> <p><span style="font-size: 18px;"><br></span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5899014778325123" data-s="300,640" src="/upload/d357fb4372a323e85699b0ec3fb09096.png" data-type="png" data-w="812" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">由于父结点15是黑色结点,因此这种情况并不会破坏红黑树的规则,无需做任何调整。</span></p> <p><br></p> <p><br></p> <p style="white-space: normal;"><span style="font-size: 18px;">2.向原红黑树插入值为<strong>21</strong>的新结点:</span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><br></span></p> <p style="white-space: normal;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.7118226600985221" data-s="300,640" src="/upload/2580d6f6f1180908e4bf0edd22ccaf2d.png" data-type="png" data-w="812" style=""></p> <p style="white-space: normal;text-align: center;"><br></p> <p style="white-space: normal;"><span style="font-size: 18px;">由于父结点22是红色结点,因此这种情况打破了红黑树的规则4(每个红色结点的两个子结点都是黑色),必须进行调整,使之重新符合红黑树的规则。</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/9e411f18f3abe287f50daf39934c1d7b.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/2bd8267888d317056df7c57b9367f84d.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;"><strong>变色:</strong></span></p> <p style="text-align: left;"><span style="font-size: 18px;"><strong><br></strong></span></p> <p style="text-align: left;"><span style="font-size: 18px;">为了重新符合红黑树的规则,尝试把红色结点变为黑色,或者把黑色结点变为红色。</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">下图所表示的是红黑树的一部分(子树),新插入的结点Y是红色结点,它的父亲结点X也是红色的,不符合规则4,因此我们可以把结点X从红色变成黑色:</span></p> <p style="text-align: left;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.4762773722627737" data-s="300,640" src="/upload/e17b415291b277fc7e75afa7a2c37426.png" data-type="png" data-w="548" style="text-align: center;width: 423px;height: 202px;"></p> <p style="text-align: left;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">但是,仅仅把一个结点变色,会导致相关路径凭空多出一个黑色结点,这样就打破了规则5。因此,我们需要对其他结点做进一步的调整,后文会详细说明。</span></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><br></p> <p style="text-align: left;"><strong><span style="font-size: 18px;">左旋转:</span></strong></p> <p style="text-align: left;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p style="text-align: left;"><strong><span style="font-size: 18px;">逆时针</span></strong><span style="font-size: 18px;">旋转红黑树的两个结点,使得父结点被自己的右孩子取代,而自己成为自己的左孩子。说起来很怪异,大家看下图:</span></p> <p style="text-align: left;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5007496251874063" data-s="300,640" src="/upload/9e10d20782cd5e5b1b7d7e91bd345639.png" data-type="png" data-w="667" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">图中,身为右孩子的Y取代了X的位置,而X变成了自己的左孩子。此为左旋转。</span></p> <p style="text-align: left;"><br></p> <p style="text-align: left;"><br></p> <p style="white-space: normal;"><strong><span style="font-size: 18px;">右旋转:</span></strong></p> <p style="white-space: normal;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p style="white-space: normal;"><strong><span style="font-size: 18px;">顺时针</span></strong><span style="font-size: 18px;">旋转红黑树的两个结点,使得父结点被自己的左孩子取代,而自己成为自己的右孩子。大家看下图:</span></p> <p style="white-space: normal;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.44086021505376344" data-s="300,640" src="/upload/72fa6246f7013f27bcd758bb3fb7e99a.png" data-type="png" data-w="744" style=""></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><span style="font-size: 18px;">图中,身为左孩子的Y取代了X的位置,而X变成了自己的右孩子。此为右旋转。</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/e99d1a4e4d02f6e4128937c20efc991.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/9f776d2b62180b32d7de91466eef8781.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/92fe9229f37b79dd2f62864b66c67304.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><strong><span style="font-size: 18px;"><br></span></strong></p> <p style="text-align: left;"><strong><span style="font-size: 18px;">局面1:</span></strong><span style="font-size: 18px;">新结点(A)位于树根,没有父结点。</span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.3061224489795917" data-s="300,640" src="/upload/f66844ec5a7a02b59c52da6db10dba03.png" data-type="png" data-w="147" style=""></p> <p style="text-align: center;"><span style="color: rgb(0, 82, 255);font-size: 16px;">(空心三角形代表结点下面的子树)</span></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">这种局面,直接让新结点变色为黑色,规则2得到满足。同时,黑色的根结点使得每条路径上的黑色结点数目都增加了1,所以并没有打破规则5。</span><br></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.4444444444444444" data-s="300,640" src="/upload/3a844c915aed5626d456a3b6ab1eaedd.png" data-type="png" data-w="432" style=""></p> <p style="text-align: center;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="font-size: 18px;">局面2:</span></strong><span style="font-size: 18px;">新结点(B)的父结点是黑色。</span></p> <p style="white-space: normal;text-align: left;"><br></p> <p style="white-space: normal;text-align: left;"><span style="font-size: 18px;">这种局面,新插入的红色结点B并没有打破红黑树的规则,所以不需要做任何调整。</span></p> <p style="white-space: normal;text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.5183246073298429" data-s="300,640" src="/upload/a64b4e366a4cd4c512a437bf87046f81.png" data-type="png" data-w="191" style=""></p> <p style="white-space: normal;text-align: left;"><br></p> <p style="white-space: normal;text-align: left;"><strong><span style="font-size: 18px;">局面3:</span></strong><span style="font-size: 18px;">新结点(D)的父结点和叔叔结点都是红色。</span></p> <p style="white-space: normal;text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.2418300653594772" data-s="300,640" src="/upload/d0d79311a023b8a65fd9e0e97cd996b0.png" data-type="png" data-w="306" style="width: 271px;height: 337px;"></p> <p style="white-space: normal;text-align: left;"><span style="font-size: 18px;">这种局面,两个红色结点B和D连续,违反了规则4。因此我们先让结点B变为黑色:</span></p> <p style="white-space: normal;text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.532033426183844" data-s="300,640" src="/upload/6927168e4a8077be336aafbbf184526e.png" data-type="png" data-w="718" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;">这样一来,结点B所在路径凭空多了一个黑色结点,打破了规则5。因此我们让结点A变为红色:</span><br></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5501392757660167" data-s="300,640" src="/upload/5a2e38705c2565649203e3d440894dd2.png" data-type="png" data-w="718" style=""></p> <p style="text-align: left;"><br></p> <p style="white-space: normal;text-align: left;"><span style="text-align: left;font-size: 18px;">这时候,结点A和C又成为了连续的红色结点,我们再让结点C变为黑色:</span></p> <p style="white-space: normal;text-align: left;"><span style="text-align: left;font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.532033426183844" data-s="300,640" src="/upload/f8b41db1e57b195db17f13d7ef8cd815.png" data-type="png" data-w="718" style=""></p> <p style="white-space: normal;text-align: left;"><br></p> <p style="white-space: normal;text-align: left;"><span style="text-align: left;font-size: 18px;">经过上面的调整,这一局部重新符合了红黑树的规则。<br></span></p> <p style="white-space: normal;text-align: left;"><br></p> <p style="white-space: normal;text-align: left;"><br></p> <p style="white-space: normal;text-align: left;"><span style="text-align: left;font-size: 18px;"><strong style="text-align: left;white-space: normal;">局面4:</strong><span style="text-align: left;">新结点(D)的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的右孩子,父结点(B)是祖父结点的左孩子。</span></span></p> <p style="white-space: normal;text-align: left;"><span style="text-align: left;font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.3310104529616724" data-s="300,640" src="/upload/a58b6719551a5b20bbf9b2b3dac21de.png" data-type="png" data-w="287" style="width: 231px;height: 308px;"></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;">我们以结点B为轴,做一次左旋转,使得新结点D成为父结点,原来的父结点B成为D的左孩子:</span></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5315068493150685" data-s="300,640" src="/upload/ae50a681975fd66de2a0d3567ac6222b.png" data-type="png" data-w="730" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;">这样一来,进入了局面5。</span></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><strong style="font-size: 18px;text-align: left;white-space: normal;">局面5:</strong><span style="font-size: 18px;text-align: left;">新结点(D)的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的左孩子,父结点(B)是祖父结点的左孩子。</span></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="1.254071661237785" data-s="300,640" src="/upload/3968d5f092c8a3593dfe73d4239174c8.png" data-type="png" data-w="307" style="width: 260px;height: 326px;"></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;">我们以结点A为轴,做一次右旋转,使得结点B成为祖父结点,结点A成为结点B的右孩子:</span></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5039267015706806" data-s="300,640" src="/upload/d5f64bfbb325e12b743cf7f60344f07a.png" data-type="png" data-w="764" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;">接下来,我们让结点B变为黑色,结点A变为红色:<br></span></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5449591280653951" data-s="300,640" src="/upload/cb1199d53e981b18a9944a52c3ab245e.png" data-type="png" data-w="734" style=""></p> <p style="text-align: left;"><span style="font-size: 18px;text-align: left;">经过上面的调整,这一局部重新符合了红黑树的规则。</span></p> <p style="text-align: left;"><br></p> <p style="text-align: left;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">以上就是红黑树插入操作所涉及的5种局面。</span><br></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">或许有人会问,如果局面4和局面5当中的父结点B是祖父结点A的右孩子该怎么办呢?<br></span></p> <p style="text-align: left;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: left;"><span style="font-size: 18px;">很简单,如果局面4中的父结点B是右孩子,则成为了局面5的镜像,原本的右旋操作改为左旋;如果<span style="text-align: left;">局面5中的父结点B是右孩子,则成为了局面4的镜像,原本的左旋操作改为右旋。</span></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/14c5bb4d66884bb3ce44194ddbfbfe48.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/339eec43a96b440a0e6253c3a80c2e8a.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">给定下面这颗红黑树,新插入的结点是21:</span></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.701120797011208" data-s="300,640" src="/upload/1305bce401c2cb8908627b49844db614.png" data-type="png" data-w="803" style=""></p> <p style="white-space: normal;"><br></p> <p style="white-space: normal;"><span style="font-size: 18px;">显然,新结点21和它的父结点22是连续的红色结点,违背了规则4,我们应该如何调整呢?</span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><br></span></p> <p style="white-space: normal;"><span style="font-size: 18px;">让我们回顾一下刚才讲的5种局面,当前的情况符合局面3:<br></span></p> <p style="white-space: normal;"><span style="font-size: 18px;">“<span style="font-size: 18px;text-align: left;">新</span><span style="font-size: 18px;text-align: left;">结点的父结点和叔叔结点都是红色</span><span style="font-size: 18px;text-align: left;">。</span>”</span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><br></span></p> <p style="white-space: normal;"><span style="font-size: 18px;">于是我们经过三次变色,22变为黑色,25变为红色,27变为黑色:<br></span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><br></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.701120797011208" data-s="300,640" src="/upload/1b162e9d501a0941d5f057563e66f6aa.png" data-type="png" data-w="803" style=""></p> <p style="white-space: normal;"><span style="font-size: 18px;"></span><br></p> <p style="white-space: normal;"><span style="font-size: 18px;">经过上面的调整,以结点25为根的子树符合了红黑树规则,但结点25和结点17成为了连续的红色结点,违背规则4。</span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><br></span></p> <p style="white-space: normal;"><span style="font-size: 18px;">于是,我们把结点25看做一个新结点,正好符合局面5的镜像:<br></span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><span style="font-size: 18px;text-align: left;">“新结点的父结点是红色,叔叔结点是黑色或者没有叔叔,且新结点是父结点的右孩子,父结点是祖父结点的右孩子”</span></span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><span style="font-size: 18px;text-align: left;"><br></span></span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><span style="font-size: 18px;text-align: left;">于是我们以根结点13为轴进行左旋转,使得结点17成为了新的根结点:<br></span></span></p> <p style="white-space: normal;"><span style="font-size: 18px;"><span style="font-size: 18px;text-align: left;"><br></span></span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.625" data-s="300,640" src="/upload/5da356a9cf922b9f5f5c97d552cde4b6.png" data-type="png" data-w="776" style=""></p> <p style="white-space: normal;"><span style="font-size: 18px;"><span style="font-size: 18px;text-align: left;"></span></span><br></p> <p style="white-space: normal;"><span style="font-size: 18px;">接下来,让结点17变为黑色,结点13变为红色:<br></span></p> <p><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.6378865979381443" data-s="300,640" src="/upload/bd46e5c4f246f7de037b1a6f9560686f.png" data-type="png" data-w="776" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: left;"><span style="font-size: 18px;">如此一来,我们的红黑树变得重新符合规则。</span></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/f73b59c3d15ae6d7559c1935a1fe7175.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5722713864306784" data-s="300,640" src="/upload/f452be2d1bd9b67dc724ed076baa1e30.png" data-type="png" data-w="678" style=""></p> <p style="text-align: center;"><br></p> <p style="text-align: center;"><img class="rich_pages" data-ratio="0.5773809523809523" data-s="300,640" src="/upload/d95677e522fa5b38d46c76038d067545.png" data-type="png" data-w="672" style=""></p> <p style="white-space: normal;line-height: 20.48px;text-align: center;"><br></p> <p style="white-space: normal;line-height: 20.48px;text-align: center;"><br></p> <p style="white-space: normal;line-height: 28.4444px;text-align: center;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 18px;letter-spacing: 0.544px;text-align: center;background-color: rgb(255, 255, 255);">—————END—————</span></p> <p style="white-space: normal;line-height: 28.4444px;text-align: center;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 18px;letter-spacing: 0.544px;text-align: center;background-color: rgb(255, 255, 255);"><br></span></p> <p style="white-space: normal;line-height: 28.4444px;text-align: center;"><br></p> <p style="letter-spacing: 0.544px;font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;widows: 1;line-height: 25.6px;text-align: center;"><span style="font-size: 18px;line-height: 28.8px;">喜欢本文的朋友,欢迎关注公众号 </span><span style="font-size: 18px;line-height: 28.8px;color: rgb(255, 76, 0);"><strong>程序员小灰</strong></span><span style="font-size: 18px;line-height: 28.8px;">,收看更多精彩内容</span></p> <p style="letter-spacing: 0.544px;font-family: Avenir, -apple-system-font, 微软雅黑, sans-serif;widows: 1;line-height: 25.6px;text-align: center;"><img data-copyright="0" data-ratio="1" data-s="300,640" data-type="jpeg" data-w="344" src="/upload/37f513ecb7627cdbb355876dab88096.jpg" style="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;box-sizing: border-box !important;visibility: visible !important;width: 333px !important;"><span style="font-family: mp-quote, -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;"></span></p> <section powered-by="xiumi.us"> <section> <section> <pre style="font-size: inherit;color: inherit;line-height: inherit;"> <section data-tools="135编辑器" data-id="94250" style="letter-spacing: 0.544px;white-space: normal;border-width: 0px;border-style: none;border-color: initial;"> <section data-tools="135编辑器" data-id="91842" style="border-width: 0px;border-style: none;border-color: initial;"> <section style="text-align: right;width: auto;"> <section style="display: inline-block;clear: both;"> <section data-brushtype="text" style="padding: 18px 15px 20px 10px;color: rgb(86, 146, 214);text-align: center;letter-spacing: 1.5px;background-image: url("https://mmbiz.qpic.cn/mmbiz_png/Pn4Sm0RsAuhpplm16ibb8iaib7RoGQ5iaHEdy66AHd7QqL7A2s5icSBE0aw4iaKOKPnXGYxQPhG7VMpbbYV6VJprSh7w/640?wx_fmt=png");background-size: 100% 100%;background-repeat: no-repeat;"> <section style="display: flex;justify-content: center;align-items: center;"> <section style="margin-left: 2px;font-size: 16px;word-spacing: 2px;width: 20px;"> <img data-ratio="0.8936170212765957" data-type="png" data-w="47" src="/upload/737696b8734b6f688ae95660c4411917.png" style="margin-bottom: -6px;box-sizing: border-box !important;visibility: visible !important;width: 20px !important;"> </section> <section data-brushtype="text" style="word-spacing: 2px;font-size: 14px;color: rgb(51, 51, 51);"> <span style="font-family: 楷体, 楷体_GB2312, SimKai;">点个[在看],是对小灰最大的支持!</span> </section> <p><br></p> </section> </section> </section> </section> </section> </section></pre> </section> </section> </section>
作者:微信小助手
<p data-mpa-powered-by="yiban.io" style="white-space: normal;max-width: 100%;min-height: 1em;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;">首先贴出一张图:</p> <figure style="max-width: 100%;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.7390753641545282" data-type="png" data-w="1579" title="Ym8V9H.png" src="/upload/aa4525467322f78881d3476abbb68b64.png" style="margin-right: auto;margin-left: auto;font-size: inherit;color: inherit;line-height: inherit;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"> <figcaption style="margin-top: 10px;max-width: 100%;line-height: inherit;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <br> </figcaption> </figure> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">前几天写了一篇<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">AQS</code>相关的文章:<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=Mzg5ODA5NDIyNQ==&mid=2247484160&idx=1&sn=612c23df04e7eea01259e2fcbec8dff0&chksm=c06686fef7110fe8e5c571d28f9219427911795ea41e9496597a47a3758072112c65f00f8180&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" data-linktype="2" hasload="1" style="color: var(--weui-LINK);-webkit-tap-highlight-color: rgba(0, 0, 0, 0);cursor: pointer;max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">我画了35张图就是为了让你深入 AQS</a>,反响不错,还上了<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">博客园首页编辑推荐</strong>,有生之年系列呀,哈哈。</p> <figure style="max-width: 100%;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.4226618705035971" data-type="png" data-w="1112" title="image.png" src="/upload/793b9cc3808c1727c2e3866c07d1d4f4.png" style="margin-right: auto;margin-left: auto;font-size: inherit;color: inherit;line-height: inherit;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 677px !important;visibility: visible !important;"> <figcaption style="margin-top: 10px;max-width: 100%;line-height: inherit;text-align: center;color: rgb(153, 153, 153);font-size: 0.7em;box-sizing: border-box !important;overflow-wrap: break-word !important;"> image.png </figcaption> </figure> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">这次趁热打铁再写一篇<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">ThreadLocal</code>的文章,同样是深入原理,图文并茂。</p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">全文共10000+字,31张图,这篇文章同样耗费了不少的时间和精力才创作完成,原创不易,请大家多多关注我的公众号</strong><span style="color: rgb(0, 0, 0);"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 16px;letter-spacing: 0.544px;text-align: right;background-color: rgb(255, 255, 255);">壹枝花算不算浪漫</span></strong></span><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">,感谢。</strong></p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">对于<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">ThreadLocal</code>,大家的第一反应可能是很简单呀,线程的变量副本,每个线程隔离。那这里有几个问题大家可以思考一下:</p> <ul class="list-paddingleft-2" style="padding-left: 32px;max-width: 100%;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;overflow-wrap: break-word !important;"> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal</strong>的key是<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">弱引用</strong>,那么在 threadLocal.get()的时候,发生<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">GC之后</strong>,key是否<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">为null</strong>?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal</strong>中<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap</strong>的<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">数据结构</strong>?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap</strong>的<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">Hash算法</strong>?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap</strong>中<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">Hash冲突</strong>如何解决?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap</strong>扩容机制?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap</strong>中过期key的清理机制?<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">探测式清理</strong>和<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">启发式清理</strong>流程?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.set()</strong>方法实现原理?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.get()</strong>方法实现原理?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">项目中<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal</strong>使用情况?遇到的坑?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">……</span></p></li> </ul> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">上述的一些问题你是否都已经掌握的很清楚了呢?本文将围绕这些问题使用图文方式来剖析<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">ThreadLocal</code>的<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">点点滴滴</strong>。</p> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">全文目录</strong></p> <ol class="list-paddingleft-2" style="padding-left: 32px;max-width: 100%;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;overflow-wrap: break-word !important;"> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal</strong>代码演示</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal</strong>的数据结构</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;">GC 之后key<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">是否为null</strong>?</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal.set()</strong>方法源码详解</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap Hash算法</strong></p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap Hash冲突</strong></p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.set()</strong>详解<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">7.1 <strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.set()</strong>原理图解<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">7.2 <strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.set()</strong>源码详解</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap</strong>过期key的<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">探测式清理</strong>流程</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap扩容机制</strong></p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.get()</strong>详解<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">10.1 <strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.get()</strong>图解<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">10.2 <strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap.get()</strong>源码详解</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocalMap</strong>过期key的<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">启发式清理</strong>流程</p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">InheritableThreadLocal</strong></p></li> <li style="margin-bottom: 0.5em;max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><p style="max-width: 100%;min-height: 1em;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal</strong>项目中使用实战<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">13.1 <strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal使用场景</strong><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">13.2 <strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">分布式TraceId解决方案</strong></p></li> </ol> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">注明:</strong> 本文源码基于<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">JDK 1.8</code></p> <h3 style="margin-top: 1.5em;margin-right: 5px;margin-bottom: 2em;padding: 8px 15px;font-weight: bold;font-size: 1.3em;max-width: 100%;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;white-space: normal;line-height: inherit;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal代码演示</span></h3> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">我们先看下<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">ThreadLocal</code>使用示例:</p> <pre style="max-width: 100%;color: inherit;font-size: inherit;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="margin-right: 2px;margin-left: 2px;padding: 0.5em;max-width: 100%;line-height: 15px;font-size: 11px;word-spacing: -3px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);box-sizing: border-box !important;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"><span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">public</span> <span style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);">class</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);">ThreadLocalTest</span> </span>{<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">private</span> List<String> messages = Lists.newArrayList();<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="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">public</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">static</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">final</span> ThreadLocal<ThreadLocalTest> holder = ThreadLocal.withInitial(ThreadLocalTest::<span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">new</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="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="max-width: 100%;font-size: inherit;line-height: inherit;">public</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;">static</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;">void</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);">add</span><span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);">(String message)</span> </span>{<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> holder.get().messages.add(message);<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="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="max-width: 100%;font-size: inherit;line-height: inherit;">public</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;">static</span> List<String> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);">clear</span><span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);">()</span> </span>{<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> List<String> messages = holder.get().messages;<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> holder.remove();<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;"> System.out.println(<span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">"size: "</span> + holder.get().messages.size());<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">return</span> messages;<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="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(248, 35, 117);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;"><span style="max-width: 100%;font-size: inherit;line-height: inherit;">public</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;">static</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;">void</span> <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(165, 218, 45);">main</span><span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(255, 152, 35);">(String[] args)</span> </span>{<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> ThreadLocalTest.add(<span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">"一枝花算不算浪漫"</span>);<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> System.out.println(holder.get().messages);<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"> ThreadLocalTest.clear();<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;"></code></pre> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">打印结果:</p> <pre style="max-width: 100%;color: inherit;font-size: inherit;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="margin-right: 2px;margin-left: 2px;padding: 0.5em;max-width: 100%;line-height: 15px;font-size: 11px;word-spacing: -3px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);box-sizing: border-box !important;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;">[一枝花算不算浪漫]<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;">size: <span style="max-width: 100%;font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);box-sizing: border-box !important;overflow-wrap: inherit !important;word-break: inherit !important;">0</span><br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></code></pre> <p style="margin-top: 1.5em;margin-bottom: 1.5em;max-width: 100%;min-height: 1em;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"><code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">ThreadLocal</code>对象可以提供线程局部变量,每个线程<code style="margin-right: 2px;margin-left: 2px;padding: 2px 4px;max-width: 100%;overflow-wrap: break-word;font-size: inherit;line-height: inherit;border-radius: 4px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);box-sizing: border-box !important;">Thread</code>拥有一份自己的<strong style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">副本变量</strong>,多个线程互不干扰。</p> <h3 style="margin-top: 1.5em;margin-right: 5px;margin-bottom: 2em;padding: 8px 15px;font-weight: bold;font-size: 1.3em;max-width: 100%;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;white-space: normal;line-height: inherit;letter-spacing: 2px;background-image: linear-gradient(to right bottom, rgb(0, 188, 212), rgb(63, 81, 181));background-color: rgb(63, 81, 181);color: rgb(255, 255, 255);border-left: 10px solid rgb(51, 51, 51);border-radius: 5px;text-shadow: rgb(102, 102, 102) 1px 1px 1px;box-shadow: rgb(102, 102, 102) 1px 1px 2px;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;font-size: inherit;color: inherit;line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;">ThreadLocal的数据结构</span></h3> <figure style="max-width: 100%;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-ratio="0.6275626423690205" data-type="png" da
作者:微信小助手
<p style="text-align: center;"><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">(给</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);">ImportNew</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">加星标,提高Java技能)</span></p> <blockquote> <p><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">作者:</span><span style="font-size: 14px;">fredalxin</span></p> </blockquote> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">线上故障主要会包括 CPU、磁盘、内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍。同时例如 jstack、jmap 等工具也是不囿于一个方面的问题的,基本上出问题就是 df、free、top 三连,然后依次 jstack、jmap 伺候,具体问题具体分析即可。<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h1 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">CPU</span></strong></span></h1> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">一般来讲我们首先会排查 CPU 方面的问题。CPU 异常往往还是比较好定位的。原因包括业务逻辑问题(死循环)、频繁 gc 以及上下文切换过多。而最常见的往往是业务逻辑(或者框架逻辑)导致的,可以使用 jstack 来分析对应的堆栈情况。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">使用 jstack 分析 CPU 问题</span></strong> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">我们先用 ps 命令找到对应进程的 pid(如果你有好几个目标进程,可以先用 top 看一下哪个占用比较高)。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">接着用top -H -p pid来找到 CPU 使用率比较高的一些线程</span> </section> <p><img data-ratio="0.353125" data-type="jpeg" data-w="640" src="/upload/a9cfc6faf81826a02e54a743d4c1740c.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="204"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">然后将占用最高的 pid 转换为 16 进制printf '%x\n' pid得到 nid</span> </section> <p><img data-ratio="0.14901960784313725" data-type="jpeg" data-w="510" src="/upload/24ea359c0cda33e63900b1814295bdae.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="510" data-backh="76"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">接着直接在 jstack 中找到相应的堆栈信息jstack pid |grep 'nid' -C5 –color</span> </section> <p><img data-ratio="0.2435754189944134" data-type="jpeg" data-w="1790" src="/upload/e29e1f887649321a516e4d209ff15405.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="141"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">可以看到我们已经找到了 nid 为 0x42 的堆栈信息,接着只要仔细分析一番即可。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当然更常见的是我们对整个 jstack 文件进行分析,通常我们会比较关注 WAITING 和 TIMED_WAITING 的部分,BLOCKED 就不用说了。我们可以使用命令cat jstack.log | grep "java.lang.Thread.State" | sort -nr | uniq -c来对 jstack 的状态有一个整体的把握,如果 WAITING 之类的特别多,那么多半是有问题啦。</span> </section> <p><img data-ratio="0.2037914691943128" data-type="jpeg" data-w="1266" src="/upload/5d58a0157fb8af877ece961e8fe38ac2.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="118"></p> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">频繁 gc</span></strong> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当然我们还是会使用 jstack 来分析问题,但有时候我们可以先确定下 gc 是不是太频繁,使用jstat -gc pid 1000命令来对 gc 分代变化情况进行观察,1000 表示采样间隔(ms),S0C/S1C、S0U/S1U、EC/EU、OC/OU、MC/MU 分别代表两个 Survivor 区、Eden 区、老年代、元数据区的容量和使用量。YGC/YGT、FGC/FGCT、GCT 则代表 YoungGc、FullGc 的耗时和次数以及总耗时。如果看到 gc 比较频繁,再针对 gc 方面做进一步分析,具体可以参考一下 gc 章节的描述。</span> </section> <p><img data-ratio="0.11276223776223776" data-type="jpeg" data-w="2288" src="/upload/4bb37799134ce368dae761a847a03ef7.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="65"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">上下文切换</span></strong> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">针对频繁上下文问题,我们可以使用vmstat命令来进行查看</span> </section> <p><img data-ratio="0.22255192878338279" data-type="jpeg" data-w="1348" src="/upload/467b3814e02745df9ebd04c5153f5585.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="129"></p> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">cs(context switch)一列则代表了上下文切换的次数。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果我们希望对特定的 pid 进行监控那么可以使用 pidstat -w pid命令,cswch 和 nvcswch 表示自愿及非自愿切换。</span> </section> <section style="line-height: 1.5em;"> <img data-ratio="0.46875" data-type="jpeg" data-w="640" src="/upload/6ab385e08bffe7eff62570533a535e26.jpg" data-backw="578" data-backh="271" style="margin: 10px auto;border-style: none;display: block;width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;"> </section> <h1 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h1> <h1 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">磁盘</span></strong></span></h1> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">磁盘问题和 CPU 一样是属于比较基础的。首先是磁盘空间方面,我们直接使用df -hl来查看文件系统状态</span> </section> <p><img data-ratio="0.12672176308539945" data-type="jpeg" data-w="1452" src="/upload/35a6965b26aac76c1e3c4bff35b11cfa.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="73"></p> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">更多时候,磁盘问题还是性能上的问题。我们可以通过 iostatiostat -d -k -x来进行分析</span> </section> <p><img data-ratio="0.22336065573770492" data-type="jpeg" data-w="1952" src="/upload/3f3b9a09957f8e85c19dd25780c1f7bc.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="129"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">最后一列%util可以看到每块磁盘写入的程度,而rrqpm/s以及wrqm/s分别表示读写速度,一般就能帮助定位到具体哪块磁盘出现问题了。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">另外我们还需要知道是哪个进程在进行读写,一般来说开发自己心里有数,或者用 iotop 命令来进行定位文件读写的来源。</span> </section> <p><img data-ratio="0.253125" data-type="jpeg" data-w="2560" src="/upload/bedd41d69a925a9990d11c74edabcb29.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="146"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">不过这边拿到的是 tid,我们要转换成 pid,可以通过 readlink 来找到 pidreadlink -f /proc/*/task/tid/../..。</span> </section> <p><img data-ratio="0.08898305084745763" data-type="jpeg" data-w="944" src="/upload/246cb71c8d17dd3ece8baeed88fba10c.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="51"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">找到 pid 之后就可以看这个进程具体的读写情况cat /proc/pid/io</span> </section> <p><img data-ratio="0.4265625" data-type="jpeg" data-w="640" src="/upload/2e0f49a7a13101d86250106a5d68a2c9.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="247"></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">我们还可以通过 lsof 命令来确定具体的文件读写情况lsof -p pid</span> </section> <p><img data-ratio="0.56875" data-type="jpeg" data-w="640" src="/upload/6b84e0fd6415d503fc1341f49b3b139f.jpg" style="margin: 10px auto;border-style: none;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="329"></p> <h1 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h1> <h1 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">内存</span></strong></span></h1> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;
作者:微信小助手
<section style="display: none;" data-tools="新媒体管家" data-label="powered by xmt.cn" data-mpa-powered-by="yiban.io"> <br> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;margin-top: -10px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial;margin-left: 8px;margin-right: 8px;font-size: 16px;"> <p><span style="color: rgb(178, 178, 178);letter-spacing: 0px;"><br></span></p> <p><span style="color: rgb(178, 178, 178);letter-spacing: 0px;">作者:黄华,腾讯 TEG 云架构平台部研�
作者:微信小助手
<section style="display: none;" data-tools="新媒体管家" data-label="powered by xmt.cn" data-mpa-powered-by="yiban.io"> <br> </section> <section style="font-size: 15px;color: rgb(62, 62, 62);line-height: 2;word-spacing: 1px;letter-spacing: 0px;font-family: Optima-Regular, PingFangTC-light;"> <section style="max-width: 100%;letter-spacing: 0.544px;white-space: normal;text-align: left;font-size: 15px;background-color: rgb(255, 255, 255);color: rgb(62, 62, 62);word-spacing: 1px;line-height: 27.2px;font-family: Helvetica, Arial, sans-serif;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin: 8px;padding: 10px;max-width: 100%;box-sizing: border-box;line-height: 25.6px;border-radius: 10px;height: auto;box-shadow: rgb(221, 221, 221) 2px 2px 8px;display: -webkit-flex;overflow-wrap: break-word !important;"> <section style="max-width: 100%;flex: 0 0 2cm;height: 78px;width: 75px;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img data-copyright="0" data-cropselx1="0" data-cropselx2="76" data-cropsely1="0" data-cropsely2="76" data-ratio="1" data-type="jpeg" data-w="258" data-width="100%" title="1803089889.png" width="100%" src="/upload/bb8461f7c0104acaa0b568a661767b3b.jpg" style="box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 75.5903px !important;"> </section> <section style="padding-right: 10px;padding-left: 10px;max-width: 100%;box-sizing: border-box;flex: 1 1 auto;height: 55px;overflow-wrap: break-word !important;"> <p style="margin-top: 5px;max-width: 100%;min-height: 1em;line-height: 35px;white-space: nowrap;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(56, 53, 53);box-sizing: border-box !important;overflow-wrap: break-word !important;"> 脚本之家</span></p> <p style="margin-top: 5px;max-width: 100%;min-height: 1em;font-size: 13px;line-height: 20px;color: rgb(127, 127, 127);box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="max-width: 100%;color: rgb(165, 165, 165);font-size: 12px;box-sizing: border-box !important;overflow-wrap: break-word !important;">你与百万开发者在一起</span></p> </section> <section style="max-width: 100%;flex: 0 0 1.5cm;color: rgb(86, 187, 55);letter-spacing: 0px;text-align: center;line-height: 6;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="margin-top: 25px;max-width: 100px;vertical-align: middle;overflow: hidden;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <section style="max-width: 100%;line-height: 2;letter-spacing: 0px;width: 55px;height: 30px;background-image: url("https://mmbiz.qpic.cn/mmbiz_gif/Ljib4So7yuWjauTdbzQb2ZYv9xTWWaw0rNXb5rzVlgtGfnbug1K1axhbhlhd2s5fYibfg8vsx9QMTdOuv2vibpqBw/640?wx_fmt=gif");background-size: 100% 100%;background-repeat: no-repeat;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <span data-role="width" style="max-width: 100%;display: inline-block;width: auto;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img border="0" data-ratio="0.86" data-type="jpeg" data-w="300" height="" title="undefined" vspace="0" width="auto" src="/upload/bb8461f7c0104acaa0b568a661767b3b.jpg" style="opacity: 0;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 55px !important;"></span> </section> </section> </section> </section> </section> <section style="margin: 10px 8px 5px;padding-right: 0em;padding-left: 0em;max-width: 100%;letter-spacing: 0.544px;white-space: normal;font-size: medium;background-color: rgb(255, 255, 255);min-height: 1em;font-family: Optima-Regular, PingFangTC-light;color: rgb(0, 0, 0);line-height: 1.75em;text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img class="__bg_gif" data-backh="39" data-backw="558" data-ratio="0.058666666666666666" data-type="gif" data-w="750" width="auto" src="/upload/5968ddb27c3ed704367e67c63f20e6eb.gif" style="color: rgb(62, 62, 62);font-size: 13.3333px;letter-spacing: 1.5px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 557.778px !important;"> </section> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;text-align: center;"><img class="rich_pages" data-cropselx1="0" data-cropselx2="562" data-cropsely1="0" data-cropsely2="313" data-ratio="0.45901639344262296" data-s="300,640" src="/upload/575b937781f005ac75a03d4d5051e9c7.png" data-type="png" data-w="610" style="width: 578px;height: 265px;"><br></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;color: rgb(123, 127, 131);">作者 l Hollis</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;text-align: left;"><span style="font-size: 15px;color: rgb(123, 127, 131);">来源 l Hollis(ID:hollischuang)</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">相信很多程序员对于Linux系统都不陌生,即使自己的日常开发机器不是Linux,那么线上服务器也大部分都是的,所以,掌握常用的Linux命令也是程序员必备的技能。</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">但是,怕就怕很多人对于部分命令只是一知半解,使用不当就能导致线上故障。</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">前段时间,我们的线上应用报警,频繁FGC,需要紧急处理问题,于是有同事去线上重启机器(正常程序应该是先采集堆dump,然后再重启,方便排查是否存在内存泄露等问题)。</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">但是在重启过程中,同事发现正常的重启命令应用无反应,然后尝试使用kill命令"杀"掉Java进程,但是仍然无效。于是他私自决定使用 "kill -9"结束了进程的生命。</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">虽然应用进程被干掉了,但是随之而来带来了很多问题,首先是上游系统突然发生大量报警,对应开发找过来说调用我们的RPC服务无响应,频繁超时。</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">后来,我们又发现系统中存在部分脏数据,有些在同一个事务中需要完整更新的数据,只更新了一半…</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">为什么正常的kill无法"杀掉"进程,而kill -9就可以?为什么kill -9会引发这一连串连锁反应?正常的kill执行时,JVM会如何处理的呢?</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;">要搞清楚这些问题,我们要先从kill命令说起。</span><span style="font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"></span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><br></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mid="t9" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <section data-tools="135编辑器" data-id="93340"> <section style="margin: 10px 0%;line-height: 20px;clear: both;letter-spacing: 1.5px;text-align: center;padding-left: 1em;padding-right: 1em;box-sizing: border-box;"> <section style="display: inline-block;vertical-align: baseline;width: auto;"> <section> <section style="display: inline-block;"> <section style="display: inline-block;padding: 5px 10px;color: rgb(254, 254, 254);font-weight: bold;border-top-left-radius: 3px;border-bottom-left-radius: 3px;background-color: rgb(251, 178, 178);box-sizing: border-box;"> <p>PART</p> </section> </section> </section> </section> <section style="display: inline-block;vertical-align: baseline;width: auto;"> <section> <section style="display: inline-block;"> <section style="display: inline-block;padding: 5px 10px;color: rgb(254, 254, 254);font-weight: bold;border-top-right-radius: 3px;border-bottom-right-radius: 3px;background-color: rgb(141, 163, 215);box-sizing: border-box;"> <p style="box-sizing: border-box;">0<span data-original-title="" title="">1</span></p> </section> </section> </section> </section> </section> </section> <section data-role="paragraph"> <p><br></p> </section> <p style="text-align: center;margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 18px;"><strong>kill 命令</strong></span><br></p> <section style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;line-height: 1.75em;margin-bottom: 15px;"> <span style="font-size: 15px;"><br></span> </section> </section> </section> </section> </section> <section> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">我们都知道,想要在Linux中终止一个进程有两种方式,如果是前台进程可以使用Ctrl+C键进行终止;如果是后台进程,那么需要使用kill命令来终止。(其实Ctrl+C也是kill命令)<br></span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">kill命令的格式是:</span></p> <pre> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"> <section style="font-size: 16px;color: rgb(62, 62, 62);line-height: 1.6;letter-spacing: 0px;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;"> <pre style="font-size: inherit;color: inherit;line-height: inherit;"> <section style="line-height: 18px;font-size: 14px;letter-spacing: 0px;font-family: Consolas, Inconsolata, Courier, monospace;border-radius: 0px;color: rgb(169, 183, 198);background: rgb(40, 43, 46);padding: 0.5em;margin-left: 8px;margin-right: 8px;margin-bottom: 15px;overflow-wrap: normal !important;word-break: normal !important;overflow: auto !important;display: -webkit-box !important;"> kill[ <span style="font-size: inherit;line-height: inherit;color: rgb(238, 220, 112);overflow-wrap: inherit !important;word-break: inherit !important;">参数</span>][ <span style="font-size: inherit;line-height: inherit;color: rgb(174, 135, 250);overflow-wrap: inherit !important;word-break: inherit !important;">进程号</span>] <br>如: <br>kill 21121 <br>kill -9 21121 </section></pre> </section></pre> </section></pre> <section style="letter-spacing: 1px;line-height: 1.75em;margin-left: 8px;margin-right: 8px;margin-bottom: 15px;"> <span style="font-size: 15px;">其中[参数]是可选的,进程号可以通过jps/ps/pidof/pstree/top等工具获取。</span> </section> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">kill的命令参数有以下几种:</span></p> <blockquote> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">-l 信号,若果不加信号的编号参数,则使用“-l”参数会列出全部的信号名称</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">-a 当处理当前进程时,不限制命令名和进程号的对应关系</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">-p 指定kill 命令只打印相关进程的进程号,而不发送任何信号</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">-s 指定发送信号</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">-u 指定用户</span></p> </blockquote> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">通常情况下,我们使用的-l(信号)的时候比较多,如我们前文提到的kill -9中的9就是信号。</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">信号如果没有指定的话,默认会发出终止信号(15)。常用的信号如下:</span></p> <blockquote> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">HUP 1 终端断线</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">INT 2 中断(同 Ctrl + C)</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">QUIT 3 退出(同 Ctrl + \)</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">TERM 15 终止</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">KILL 9 强制终止</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">CONT 18 继续(与STOP相反, fg/bg命令)</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">STOP 19 暂停(同 Ctrl + Z)</span></p> </blockquote> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">比较常用的就是强制终止信号:9和终止信号:15,另外,中断信号:2其实就是我们前文提到的Ctrl + C结束前台进程。</span></p> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><span style="font-size: 15px;">那么,kill -9 和 kill -15到底有什么区别呢?该如何选择呢?</span></p> <section data-mpa-template="t" mpa-from-tpl="t"> <section data-mid="t9" mpa-from-tpl="t"> <section data-mid="" mpa-from-tpl="t"> <p style="margin-left: 8px;margin-right: 8px;letter-spacing: 1px;margin-bottom: 15px;line-height: 1.75em;"><br></p> <section data-tools="135编辑器" data-id="93340"> <section style="margin: 10px 0%;line-height: 20px;clear: both;letter-spacing: 1.5px;text-align: center;padding-left: 1em;padding-right: 1em;box-sizing: border-box;"> <section style="display: inline-block;vertical-align: baseline;width: auto;"> <section> <section style="display: inline-block;"> <section style="display: inline-block;padding: 5px 10px;color: rgb(254, 254, 254);font-weight: bold;border-top-left-radius: 3px;border-bottom-left-radius: 3px;background-color: rgb(251, 178, 178);box-sizing: border-box;"> <p>PART</p> </section> </section> </section> </section> <section style="display: inline-block;vertical-align: baseline;width: auto;"> <section> <section style="display: inline-block;"> <section style="display
作者:微信小助手
<p style="text-align: center;"><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">(给</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);">ImportNew</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">加星标,提高Java技能)</span></p> <blockquote> <p><span style="max-width: 100%;font-size: 14px;box-sizing: border-box !important;overflow-wrap: break-word !important;">转自:博客园 作者:</span><span style="font-size: 14px;">菜鸟小于 </span></p> <p><span style="font-size: 14px;">cnblogs.com/Young111/p/11519952.html?utm_source=gold_browser_extension</span></p> </blockquote> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">1:HashMap 的数据结构?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点。当链表长度超过 8 时,链表转换为红黑树。</span> </section> <pre style="overflow-x: auto;"><code style="font-size: 0.85em;font-family: Consolas, Menlo, Courier, monospace;margin: 0px 0.15em;white-space: pre;overflow: auto;display: block;padding: 0.5em;color: rgb(171, 178, 191);text-size-adjust: none;min-width: 400px;background: none 0% 0% / auto repeat scroll padding-box border-box rgb(40, 44, 52);font-weight: 400;" data-wx-hl-code="transient Node<K,V>\[\] table;" data-wx-hl-lang="Java" data-wx-hl-style="atom-one-dark"><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">transient</span> Node<K,V>\[\] table;</code></pre> <p><br></p> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">2:HashMap 的工作原理?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">HashMap 底层是 hash 数组和单向链表实现,数组中的每个元素都是链表,由 Node 内部类(实现 Map.Entry</span> <k,v> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">接口)实现,HashMap 通过 put & get 方法存储和获取。</span> </k,v> </section> <section style="line-height: 1.5em;"> <k,v> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </k,v> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">存储对象时,将 K/V 键值传给 put() 方法:</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">①、调用 hash(K) 方法计算 K 的 hash 值,然后结合数组长度,计算得数组下标;</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">②、</span> <span style="color: rgb(0, 0, 0);font-size: 15px;">调整数组大小(当容器中的元素个数大于 capacity * loadfactor 时,容器会进行扩容resize 为 2n);</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">③、</span> <span style="color: rgb(0, 0, 0);font-size: 15px;">i.如果 K 的 hash 值在 HashMap 中不存在,则执行插入,若存在,则发生碰撞;</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;">ii.如果 K 的 hash 值在 HashMap 中存在,且它们两者 equals 返回 true,则更新键值对;</span> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;">iii. 如果 K 的 hash 值在 HashMap 中存在,且它们两者 equals 返回 false,则插入链表的尾部(尾插法)或者红黑树中(树的添加方式)。</span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(0, 0, 0);font-size: 15px;">(JDK 1.7 之前使用头插法、JDK 1.8 使用尾插法)(注意:当碰撞导致链表大于 TREEIFY_THRESHOLD = 8 时,就把链表转换成红黑树)</span> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">获取对象时,将 K 传给 get() 方法:①、调用 hash(K) 方法(计算 K 的 hash 值)从而获取该键值所在链表的数组下标;②、顺序遍历链表,equals()方法查找相同 Node 链表中 K 值对应的 V 值。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">hashCode 是定位的,存储位置;equals是定性的,比较两者是否相等。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">3.当两个对象的 hashCode 相同会发生什么?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI2MTIzMzY3Mw==&mid=2247489051&idx=4&sn=651c4a067c2f1d59151f484475144c20&chksm=ea5cdb7ddd2b526bcb46214f83f80859c8603497323a3cf933e511b6f018af666dd74b0e584d&scene=21#wechat_redirect" textvalue="因为 hashCode 相同,不一定就是相等的(equals方法比较),所以两个对象所在数组的下标相同,'碰撞'就此发生。又因为 HashMap 使用链表存储对象,这个 Node 会存储到链表中。为什么要重写 hashcode 和 equals 方法?推荐看下。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">因为 hashCode 相同,不一定就是相等的(equals方法比较),所以两个对象所在数组的下标相同,"碰撞"就此发生。又因为 HashMap 使用链表存储对象,这个 Node 会存储到链表中。为什么要重写 hashcode 和 equals 方法?推荐看下。</span></a> </section> <section style="line-height: 1.5em;"> <br> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">4.你知道 hash 的实现吗?为什么要这样实现?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">JDK 1.8 中,是通过 hashCode() 的高 16 位异或低 16 位实现的:(h = k.hashCode()) ^ (h >>> 16),主要是从速度,功效和质量来考虑的,减少系统的开销,也不会造成因为高位没有参与下标的计算,从而引起的碰撞。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">5.为什么要用异或运算符?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">保证了对象的 hashCode 的 32 位值只要有一位发生改变,整个 hash() 返回值就会改变。尽可能的减少碰撞。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">6.HashMap 的 table 的容量如何确定?loadFactor 是什么?该容量如何变化?这种变化会带来什么问题?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI2MTIzMzY3Mw==&mid=2247489478&idx=4&sn=ad7321cd1948f0c8eaf955aaaa7a2046&chksm=ea5cdaa0dd2b53b67ac2b9ba12935e13cb59250180fa302bd61629968e24f8853f208790fe80&scene=21#wechat_redirect" textvalue="①、table 数组大小是由 capacity 这个参数确定的,默认是16,也可以构造时传入,最大限制是1<<30;②、loadFactor 是装载因子,主要目的是用来确认table 数组是否需要动态扩展,默认值是0.75,比如table 数组大小为 16,装载因子为 0.75 时,threshold 就是12,当 table 的实际大小超过 12 时,table就需要动态扩容;③、扩容时,调用 resize() 方法,将 table 长度变为原来的两倍(注意是 table 长度,而不是 threshold)④、如果数据很大的情况下,扩展时将会带来性能的损失,在性能要求很高的地方,这种损失很可能很致命。推荐:HashMap容量为什么总是为2的次幂? " data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">①、table 数组大小是由 capacity 这个参数确定的,默认是16,也可以构造时传入,最大限制是1<<30;</span></a> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI2MTIzMzY3Mw==&mid=2247489478&idx=4&sn=ad7321cd1948f0c8eaf955aaaa7a2046&chksm=ea5cdaa0dd2b53b67ac2b9ba12935e13cb59250180fa302bd61629968e24f8853f208790fe80&scene=21#wechat_redirect" textvalue="①、table 数组大小是由 capacity 这个参数确定的,默认是16,也可以构造时传入,最大限制是1<<30;②、loadFactor 是装载因子,主要目的是用来确认table 数组是否需要动态扩展,默认值是0.75,比如table 数组大小为 16,装载因子为 0.75 时,threshold 就是12,当 table 的实际大小超过 12 时,table就需要动态扩容;③、扩容时,调用 resize() 方法,将 table 长度变为原来的两倍(注意是 table 长度,而不是 threshold)④、如果数据很大的情况下,扩展时将会带来性能的损失,在性能要求很高的地方,这种损失很可能很致命。推荐:HashMap容量为什么总是为2的次幂? " data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">②、loadFactor 是装载因子,主要目的是用来确认table 数组是否需要动态扩展,默认值是0.75,比如table 数组大小为 16,装载因子为 0.75 时,threshold 就是12,当 table 的实际大小超过 12 时,table就需要动态扩容;</span></a> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI2MTIzMzY3Mw==&mid=2247489478&idx=4&sn=ad7321cd1948f0c8eaf955aaaa7a2046&chksm=ea5cdaa0dd2b53b67ac2b9ba12935e13cb59250180fa302bd61629968e24f8853f208790fe80&scene=21#wechat_redirect" textvalue="①、table 数组大小是由 capacity 这个参数确定的,默认是16,也可以构造时传入,最大限制是1<<30;②、loadFactor 是装载因子,主要目的是用来确认table 数组是否需要动态扩展,默认值是0.75,比如table 数组大小为 16,装载因子为 0.75 时,threshold 就是12,当 table 的实际大小超过 12 时,table就需要动态扩容;③、扩容时,调用 resize() 方法,将 table 长度变为原来的两倍(注意是 table 长度,而不是 threshold)④、如果数据很大的情况下,扩展时将会带来性能的损失,在性能要求很高的地方,这种损失很可能很致命。推荐:HashMap容量为什么总是为2的次幂? " data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">③、扩容时,调用 resize() 方法,将 table 长度变为原来的两倍(注意是 table 长度,而不是 threshold)</span></a> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">④、如果数据很大的情况下,扩展时将会带来性能的损失,在性能要求很高的地方,这种损失很可能很致命。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">7.HashMap中put方法的过程?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">答:“调用哈希函数获取Key对应的hash值,再计算其数组下标;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果没有出现哈希冲突,则直接放入数组;如果出现哈希冲突,则以链表的方式放在链表后面;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果链表长度超过阀值( TREEIFY THRESHOLD==8),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果结点的key已经存在,则替换其value即可;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果集合中的键值对大于12,调用resize方法进行数组扩容。”</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">8.数组扩容的过程?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">创建一个新的数组,其容量为旧数组的两倍,并重新计算旧数组中结点的存储位置。结点在新数组中的位置只有两种,原下标位置或原下标+旧数组的大小。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">9.拉链法导致的链表过深问题为什么不用二叉查找树代替,而选择红黑树?为什么不一直使用红黑树?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI2MTIzMzY3Mw==&mid=2247489139&idx=2&sn=9670f4aa9a1b240352b5387f776fb284&chksm=ea5cdb15dd2b5203cd904cdadf8e1061b6e1e6af6a51c9116eceee4313f889945e529381162d&scene=21#wechat_redirect" textvalue="之所以选择红黑树是为了解决二叉查找树的缺陷,二叉查找树在特殊情况下会变成一条线性结构(这就跟原来使用链表结构一样了,造成很深的问题),遍历查找会非常慢。推荐:面试问红黑树,我脸都绿了。而红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,引入红黑树就是为了查找数据快,解决链表查询深度的问题,我们知道红黑树属于平衡二叉树,但是为了保持“平衡”是需要付出代价的,但是该代价所损耗的资源要比遍历线性链表要少,所以当长度大于8的时候,会使用红黑树,如果链表长度很短的话,根本不需要引入红黑树,引入反而会慢。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">之所以选择红黑树是为了解决二叉查找树的缺陷,二叉查找树在特殊情况下会变成一条线性结构(这就跟原来使用链表结构一样了,造成很深的问题),遍历查找会非常慢。推荐:面试问红黑树,我脸都绿了。</span></a> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI2MTIzMzY3Mw==&mid=2247489139&idx=2&sn=9670f4aa9a1b240352b5387f776fb284&chksm=ea5cdb15dd2b5203cd904cdadf8e1061b6e1e6af6a51c9116eceee4313f889945e529381162d&scene=21#wechat_redirect" textvalue="之所以选择红黑树是为了解决二叉查找树的缺陷,二叉查找树在特殊情况下会变成一条线性结构(这就跟原来使用链表结构一样了,造成很深的问题),遍历查找会非常慢。推荐:面试问红黑树,我脸都绿了。而红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,引入红黑树就是为了查找数据快,解决链表查询深度的问题,我们知道红黑树属于平衡二叉树,但是为了保持“平衡”是需要付出代价的,但是该代价所损耗的资源要比遍历线性链表要少,所以当长度大于8的时候,会使用红黑树,如果链表长度很短的话,根本不需要引入红黑树,引入反而会慢。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">而红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,引入红黑树就是为了查找数据快,解决链表查询深度的问题,我们知道红黑树属于平衡二叉树,但是为了保持“平衡”是需要付出代价的,但是该代价所损耗的资源要比遍历线性链表要少,所以当长度大于8的时候,会使用红黑树,如果链表长度很短的话,根本不需要引入红黑树,引入反而会慢。</span></a> </section> <section style="line-height: 1.5em;"> <br> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">10.说说你对红黑树的见解?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <ul class="list-paddingleft-2"> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">每个节点非红即黑</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">根节点总是黑色的</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果节点是红色的,则它的子节点必须是黑色的(反之不一定)</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">每个叶子节点都是黑色的空节点(NIL节点)</span> </section><p><br></p></li> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度)</span> </section></li> </ul> <h4 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h4> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">11.jdk8中对HashMap做了哪些改变?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">在java 1.8中,如果链表的长度超过了8,那么链表将转换为红黑树。(桶的数量必须大于64,小于64的时候只会扩容)</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">发生hash碰撞时,java 1.7 会在链表的头部插入,而java 1.8会在链表的尾部插入</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">在java 1.8中,Entry被Node替代(换了一个马甲。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">12.HashMap,LinkedHashMap,TreeMap 有什么区别?</span></strong></span></h4> <p><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;"><br></span></strong></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">HashMap 参考其他问题;关注微信公众号:互联网架构师,在后台回复:2T,可以获取架构师资源干货。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">LinkedHashMap 保存了记录的插入顺序,在用 Iterator 遍历时,先取到的记录肯定是先插入的;遍历比 HashMap 慢;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">TreeMap 实现 SortMap 接口,能够把它保存的记录根据键排序(默认按键值升序排序,也可以指定排序的比较器)</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">13.HashMap & TreeMap & LinkedHashMap 使用场景?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">一般情况下,使用最多的是 HashMap。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">HashMap:在 Map 中插入、删除和定位元素时;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">TreeMap:在需要按自然顺序或自定义顺序遍历键的情况下;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">LinkedHashMap:在需要输出的顺序和输入的顺序相同的情况下。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">14.HashMap 和 HashTable 有什么区别?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">①、HashMap 是线程不安全的,HashTable 是线程安全的;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">②、由于线程安全,所以 HashTable 的效率比不上 HashMap;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">③、HashMap最多只允许一条记录的键为null,允许多条记录的值为null,而 HashTable不允许;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">④、HashMap 默认初始化数组的大小为16,HashTable 为 11,前者扩容时,扩大两倍,后者扩大两倍+1;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">⑤、HashMap 需要重新计算 hash 值,而 HashTable 直接使用对象的 hashCode</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">15.Java 中的另一个线程安全的与 HashMap 极其类似的类是什么?同样是线程安全,它与 HashTable 在线程同步上有什么不同?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">ConcurrentHashMap 类(是 Java并发包 java.util.concurrent 中提供的一个线程安全且高效的 HashMap 实现)。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">HashTable 是使用 synchronize 关键字加锁的原理(就是对对象加锁);</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">而针对 ConcurrentHashMap,在 JDK 1.7 中采用 分段锁的方式;JDK 1.8 中直接采用了CAS(无锁算法)+ synchronized。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">16.HashMap & ConcurrentHashMap 的区别?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">除了加锁,原理上无太大区别。另外,HashMap 的键值对允许有null,但是ConCurrentHashMap 都不允许。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><strong><span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);">17.为什么 ConcurrentHashMap 比 HashTable 效率要高?</span></strong></h4> <p><strong><span style="font-size: 15px;letter-spacing: normal;color: rgb(171, 25, 66);"><br></span></strong></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">HashTable 使用一把锁(锁住整个链表结构)处理并发问题,多个线程竞争一把锁,容易阻塞;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">ConcurrentHashMap</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <ul class="list-paddingleft-2"> <li style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">JDK 1.7 中使用分段锁(ReentrantLock + Segment + HashEntry),相当于把一个 HashMap 分成多个段,每段分配一把锁,这样支持多线程访问。锁粒度:基于 Segment,包含多个 HashEntry。</span> </section><p><br></p></li> <li> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">JDK 1.8 中使用 CAS + synchronized + Node + 红黑树。锁粒度:Node(首结</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">点)(实现 Map.Entry</span> <k,v> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">)。锁粒度降低了。</span> </k,v> </section></li> </ul> <h4 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h4> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">18.针对 ConcurrentHashMap 锁机制具体分析(JDK 1.7 VS JDK 1.8)</span></strong></span></h4> <p><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;"><br></span></strong></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">JDK 1.7 中,采用分段锁的机制,实现并发的更新操作,底层采用数组+链表的存储结构,包括两个核心静态内部类 Segment 和 HashEntry。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">①、Segment 继承 ReentrantLock(重入锁) 用来充当锁的角色,每个 Segment 对象守护每个散列映射表的若干个桶;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">②</span> <span style="color: rgb(0, 0, 0);font-size: 15px;">、HashEntry 用来封装映射表的键-值对;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">③、每个桶是由若干个 HashEntry 对象链接起来的链表</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <figure> <img src="/upload/875b663bf5e9df1308871d2f468c5b09.png" data-cropx1="0" data-cropx2="803" data-cropy1="0" data-cropy2="384.301329394387" data-ratio="0.47820672478206727" data-type="jpeg" data-w="803" title="" src="https://mmbiz.qpic.cn/mmbiz_jpg/9mQQWOf4KRKkSgpKCd5PAf5rFicdeHYSv09hWxTuAAR0Q0picCAUyXxiatM1VG6JdmcibkjWUkwJmzuOAgheLnOHmQ/640?wx_fmt=jpeg" style="margin-right: auto;margin-left: auto;font-size: inherit;color: inherit;line-height: inherit;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;" data-backw="578" data-backh="277"> </figure> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">JDK 1.8 中,采用Node + CAS + Synchronized来保证并发安全。取消类 Segment,直接用 table 数组存储键值对;当 HashEntry 对象组成的链表长度超过 TREEIFY_THRESHOLD 时,链表转换为红黑树,提升性能。底层变更为数组 + 链表 + 红黑树。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <figure> <img data-backh="178" data-backw="444" src="/upload/87671ba80faeb7acc92f5e22311b478e.png" data-cropx1="0" data-cropx2="629.1365313653137" data-cropy1="0" data-cropy2="252.22140221402213" data-ratio="0.40063593004769477" data-type="jpeg" data-w="629" title="" src="https://mmbiz.qpic.cn/mmbiz_jpg/9mQQWOf4KRKkSgpKCd5PAf5rFicdeHYSvbv2VRT6iaN9Xvk7s2j1IwDfqP9ianaPka23qXhiboaccZwtS6SfwGthDg/640?wx_fmt=jpeg" style="margin-right: auto;margin-left: auto;font-size: inherit;color: inherit;line-height: inherit;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 100%;height: auto;"> </figure> <h4 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h4> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">19.ConcurrentHashMap 在 JDK 1.8 中,为什么要使用内置锁 synchronized 来代替重入锁 ReentrantLock?</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">①、粒度降低了;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">②、JVM 开发团队没有放弃 synchronized,而且基于 JVM 的 synchronized 优化空间更大,更加自然。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">③、在大量的数据操作下,对于 JVM 的内存压力,基于 API 的 ReentrantLock 会开销更多的内存。</span> </section> <h4 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h4> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">20.ConcurrentHashMap 简单介绍?</span></strong></span></h4> <p><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;"><br></span></strong></span></p> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">①、重要的常量:</span></strong> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></strong> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">private transient volatile int sizeCtl;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当为负数时,-1 表示正在初始化,-N 表示 N - 1 个线程正在进行扩容;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当为 0 时,表示 table 还没有初始化;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当为其他正数时,表示初始化或者下一次进行扩容的大小。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">②、数据结构:</span></strong> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></strong> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">Node 是存储结构的基本单元,继承 HashMap 中的 Entry,用于存储数据;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">TreeNode 继承 Node,但是数据结构换成了二叉树结构,是红黑树的存储结构,用于红黑树中存储数据;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">TreeBin 是封装 TreeNode 的容器,提供转换红黑树的一些条件和锁的控制。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">③、存储对象时(put() 方法):</span></strong> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果没有初始化,就调用 initTable() 方法来进行初始化;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果没有 hash 冲突就直接 CAS 无锁插入;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果需要扩容,就先进行扩容;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果存在 hash 冲突,就加锁来保证线程安全,两种情况:一种是链表形式就直接遍历</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">到尾端插入,一种是红黑树就按照红黑树结构插入;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果该链表的数量大于阀值 8,就要先转换成红黑树的结构,break 再一次进入循环</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果添加成功就调用 addCount() 方法统计 size,并且检查是否需要扩容。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">④、扩容方法 transfer():默认容量为 16,扩容时,容量变为原来的两倍。</span></strong> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">helpTransfer():调用多个工作线程一起帮助进行扩容,这样的效率就会更高。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">⑤、获取对象时(get()方法):</span></strong> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">计算 hash 值,定位到该 table 索引位置,如果是首结点符合就返回;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">如果遇到扩容时,会调用标记正在扩容结点 ForwardingNode.find()方法,查找该结点,匹配就返回;</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">以上都不符合的话,就往下遍历结点,匹配就返回,否则最后就返回 null。</span> </section> <h4 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h4> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;">21.ConcurrentHashMap 的并发度是什么?</span></strong></span></h4> <p><span style="color: rgb(171, 25, 66);"><strong><span style="color: rgb(171, 25, 66);font-size: 15px;letter-spacing: normal;"><br></span></strong></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">程序运行时能够同时更新 ConccurentHashMap 且不产生锁竞争的最大线程数。默认为 16,且可以在构造函数中设置。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">当用户设置并发度时,ConcurrentHashMap 会使用大于等于该值的最小2幂指数作为实际并发度(假如用户设置并发度为17,实际并发度则为32)</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section donone="shifuMouseDownCard('shifu_c_030')" label="Copyright Reserved by PLAYHUDONG." style="text-align: start;white-space: normal;margin-top: 1em;margin-bottom: 1em;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);border-width: 0px;border-style: initial;border-color: initial;"> <section style="margin-left: 1em;line-height: 1.4;"> <span style="padding: 3px 8px;border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;color: rgb(255, 255, 255);background-color: rgb(255, 105, 31);font-family: inherit;text-align: inherit;text-decoration: inherit;font-size: 16px;">推荐阅读</span> <span style="margin-left: 4px;padding: 3px 8px;border-top-left-radius: 1.2em;border-top-right-radius: 1.2em;border-bottom-right-radius: 1.2em;border-bottom-left-radius: 1.2em;color: rgb(255, 255, 255);line-height: 1.2;background-color: rgb(204, 204, 204);font-family: inherit;text-align: inherit;text-decoration: inherit;border-color: rgb(249, 110, 87);font-size: 12px;">点击标题可跳转</span> </section> <section style="margin-top: -11px;padding: 22px 16px 16px;border-width: 1px;border-style: solid;border-color: rgb(255, 105, 31);color: rgb(51, 51, 51);font-size: 1em;font-family: inherit;text-align: inherit;text-decoration: inherit;"> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);font-size: 12px;text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651484002&idx=1&sn=430632e2ba0e751f33c415802b6e7659&chksm=bd25031d8a528a0b9982cedcdcfa59d51268ee08087ef980c4f89a68b0954e25a82896216640&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">HashMap 实现原理解读</a><br></span></p> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);font-size: 12px;text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651482397&idx=1&sn=bd14c50be04f29810ee44bc9c0afe105&chksm=bd2505628a528c7446bb2c585e66b65b7e4a0f12d667d66dc6cdc627703054b82036a4c6e418&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">Java HashMap源码分析</a><br></span></p> <p><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651487226&idx=1&sn=4894bfc3403f5dbcc6268620ee90ac7e&chksm=bd2517858a529e93741d87a850acf255f31d4e0cf264969fe11763877ff54aade9350b5c51d2&scene=21#wechat_redirect" data-itemshowtype="11" tab="innerlink" style="font-size: 12px;text-decoration: underline;" data-linktype="2"><span style="font-size: 12px;">HashMap 的 7 种遍历方式与性能分析!</span></a><br></p> </section> </section> <p style="caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);text-align: start;white-space: normal;"><br></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;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="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;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="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.9166666666666666" data-s="300,640" data-type="jpeg" data-w="600" width="auto" src="/upload/899866149276fa5fddb73c61ae04be64.jpg" style="box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 600px !important;"></p> <p style="text-align: right;"><span style="font-size: 14px;text-align: right;">好文章,我</span><span style="font-size: 14px;text-align: right;color: rgb(255, 41, 65);">在看</span><span style="font-size: 14px;text-align: right;">❤️</span></p>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com"> <p><br></p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin: 10px auto;height: 40px;background-color: rgb(251, 251, 251);border-bottom: 1px solid rgb(246, 246, 246);overflow: hidden;box-sizing: border-box;"><span style="display: none;"></span><span style="margin-left: -10px;display: inline-block;width: auto;height: 40px;background-color: rgb(33, 33, 34);border-bottom-right-radius: 100px;color: rgb(255, 255, 255);padding-right: 30px;padding-left: 30px;line-height: 40px;font-size: 16px;">前言</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;">话说上回HashMap跟面试官扯了半个小时之后,二面迎来了没有削弱前的钟馗,法师的钩子让安琪拉有点绝望。钟馗穿着有些微微泛黄的格子道袍,站在安琪拉对面,开始发难,其中让安琪拉印象非常深刻的是法师的synchronized 钩子。</p> <h2 data-tool="mdnice编辑器" style="font-weight: bold;font-size: 22px;margin: 10px auto;height: 40px;background-color: rgb(251, 251, 251);border-bottom: 1px solid rgb(246, 246, 246);overflow: hidden;box-sizing: border-box;"><span style="display: none;"></span><span style="margin-left: -10px;display: inline-block;width: auto;height: 40px;background-color: rgb(33, 33, 34);border-bottom-right-radius: 100px;color: rgb(255, 255, 255);padding-right: 30px;padding-left: 30px;line-height: 40px;font-size: 16px;">开场</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>面试官</strong>: 你先自我介绍一下吧!</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>安琪拉</strong>: 我是安琪拉,草丛三婊之一,最强中单(钟馗冷哼)!哦,不对,串场了,我是**,目前在--公司做--系统开发。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>面试官</strong>: 刚才听一面的同事说你们上次聊到了synchronized,你借口说要回去补篮,现在能跟我讲讲了吧?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>安琪拉</strong>: 【上来就丢钩子,都不寒暄几句,问我吃没吃】嗯嗯,是有聊到 synchronized。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>面试官</strong>: 那你跟我说说为什么会需要synchronized?什么场景下使用synchronized?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>安琪拉</strong>: 这个就要说到多线程访问共享资源了,当一个资源有可能被多个线程同时访问并修改的话,需要用到<strong>锁</strong>,还是画个图给您看一下,请看👇图:</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.6790352504638218" src="/upload/66e9c4c5805eb66cc4d28d7cffb50033.png" data-type="png" data-w="539" style="display: block;margin-right: auto;margin-left: auto;width: auto;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> 在这里插入图片描述 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>安琪拉</strong>: 如上图所示,比如在王者荣耀程序中,我们队有二个线程分别统计后裔和安琪拉的经济,A线程从内存中read 当前队伍总经济加载到线程的本地栈,进行 +100 操作之后,这时候B线程也从内存中取出经济值 + 200,将200写回内存,B线程前脚刚写完,后脚A线程将100 写回到内存中,就出问题了,我们队的经济应该是300, 但是内存中存的却是100,你说糟不糟心。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>面试官</strong>: 那你跟我讲讲用 synchronized 怎么解决这个问题的?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>安琪拉</strong>: 在访问竞态资源时加锁,因为多个线程会修改经济值,因此经济值就是静态资源,给您show 一下吧?下图是不加锁的代码和控制台的输出,请您过目:</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;">二个线程,A线程让队伍经济 +1 ,B线程让经济 + 2,分别执行一千次,正确的结果应该是3000,结果得到的却是 2845。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.875" src="/upload/b628214f1e672c58c5ee9c634a825e18.png" data-type="png" data-w="1280" style="display: block;margin-right: auto;margin-left: auto;width: auto;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> 在这里插入图片描述 </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>安琪拉</strong>: 👇这个就是加锁之后的代码和控制台的输出。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="1.00326264274062" src="/upload/374f1f65f60fc295b2091a6809be5938.png" data-type="png" data-w="1226" style="display: block;margin-right: auto;margin-left: auto;width: auto;"> <figcaption style="margin-top: 5px;text-align: center;color: #888;font-size: 14px;"> (img-6NwdhDEz-1585279691724)(/Users/zw/Library/Application Support/typora-user-images/image-20200321210555529.png)] </figcaption> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>面试官</strong>: 我看你👆用synchronized 锁住的是代码块,synchronized 还有别的<strong>作用范围</strong>吗?</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;box-sizing: border-box;margin-bottom: 16px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;font-size: 15px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;"><strong>安琪拉</strong>: 嗯嗯,synchronized 有以下三种作用范围:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;"> <p style="padding-top: 8px;padding-bottom: 8px;color: black;box-sizing: border-box;margin-bottom: 16px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;">在静态方法上加锁;</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;"> <p style="padding-top: 8px;padding-bottom: 8px;color: black;box-sizing: border-box;margin-bottom: 16px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;">在非静态方法上加锁;</p> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);font-size: 15px;font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;"> <p style="padding-top: 8px;padding-bottom: 8px;color: black;box-sizing: border-box;margin-bottom: 16px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;">在代码块上加锁;</p> <p style="padding-top: 8px;padding-bottom: 8px;color: black;box-sizing: border-box;margin-bottom: 16px;white-space: normal;text-size-adjust: auto;line-height: 1.75em;">示例代码如下</p> <pre style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"><span style="display: -webkit-box;background: url("https://mmbiz.qpic.cn/mmbiz_png/SoGf97KLurAicd1Y2Vmx8AMVibe6YvE8giavqicM6oGCTON6arW4OpAxCIUPoWNdye7lAvFx4FDc0Rqicpxbvr5lreg/640?wx_fmt=png") 10px 10px / 40px no-repeat rgb(248, 248, 248);height: 30px;width: 100%;margin-bottom: -7px;border-radius: 5px;"></span><code style="overflow-x: auto;display: -webkit-box;font-size: 14px;overflow-wrap: break-word;padding: 15px 4px 2px;margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(239, 112, 96);background: rgb(248, 248, 248);border-radius: 5px;"><span style="color: #333;font-weight: bold;line-height: 26px;">public</span> <span style="line-height: 26px;"><span style="color: #333;font-weight: bold;line-height: 26px;">class</span> <span style="color: #458;font-weight: bold;line-height: 26px;">SynchronizedSample</span> </span>{<br><br> <span style="color: #333;font-weight: bold;line-height: 26px;">private</span> <span style="color: #333;font-weight: bold;line-height: 26px;">final</span> Object lock = <span style="color: #333;font-weight: bold;line-height: 26px;">new</span> Object();<br><br> <span style="color: #333;font-weight: bold;line-height: 26px;">private</span> <span style="color: #333;font-weight: bold;line-height: 26px;">static</span> <span style="color: #333;font-weight: bold;line-height: 26px;">int</span> money = <span style="color: #008080;line-height: 26px;">0</span>;<br> <span style="color: #998;font-style: italic;line-height: 26px;">//非静态方法</span><br> <span style="line-height: 26px;"><span style="color: #333;font-weight: bold;line-height: 26px;">public</span> <span style="color: #333;font-weight: bold;line-height: 26px;">synchronized</span> <span style="color: #333;font-weight: bold;line-height: 26px;">void</span> <span style="color: #900;font-weight: bold;line-height: 26px;">noStaticMethod</span><span style="line-height: 26px;">()</span></span>{<br> money++;<br> }<br> <span style="color: #998;font-style: italic;line-height: 26px;">//静态方法</span><br> <span style="line
作者:微信小助手
<p style="text-align: center;"><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">(给</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;line-height: 22.4px;color: rgb(0, 128, 255);">ImportNew</span><span style="font-size: 14px;letter-spacing: 0.5440000295639038px;text-align: center;max-width: 100%;color: rgb(255, 41, 65);line-height: 22.4px;">加星标,提高Java技能)</span></p> <blockquote> <p style="letter-spacing: 0.5440000295639038px;white-space: normal;background-color: rgb(255, 255, 255);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;">转自:掘金 作者:何甜甜在吗</span></p> <p style="letter-spacing: 0.5440000295639038px;white-space: normal;background-color: rgb(255, 255, 255);max-width: 100%;min-height: 1em;text-align: left;box-sizing: border-box !important;overflow-wrap: break-word !important;"><span style="font-size: 14px;">juejin.im/post/5c08db5ff265da611e4d7417</span></p> </blockquote> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">公司最近在做交易系统,交易系统肯定是要和钱打交道的,和钱有关,自然而然很容易想到用float存储,但是使用float存储金额做的计算是近似计算。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"></span> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247484834&idx=1&sn=ea4af7434a399f6433d3a0ae3aac2d05&chksm=eb538094dc240982f3793e54918b128aa4b683b995ac33dfc5c45579422e24bf5fcef3e4226b&scene=21#wechat_redirect" textvalue="老板,用float做计算造成公司损失的钱都往你工资里扣。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">老板说:「用float做计算造成公司损失的钱都往你工资里扣。</a>」<a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247484834&idx=1&sn=ea4af7434a399f6433d3a0ae3aac2d05&chksm=eb538094dc240982f3793e54918b128aa4b683b995ac33dfc5c45579422e24bf5fcef3e4226b&scene=21#wechat_redirect" textvalue="老板,用float做计算造成公司损失的钱都往你工资里扣。" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1"></a></span> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">哼,扣工资就扣工资。但还是得静下心来想想为什么不能用float。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h3 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">为什么不能使用float存储金额</span></strong></span></h3> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">首先看个例子:FloatTest.java</span> </section> <pre style="overflow-x: auto;"><code style="font-size: 0.85em;font-family: Consolas, Menlo, Courier, monospace;margin: 0px 0.15em;white-space: pre;overflow: auto;display: block;padding: 0.5em;color: rgb(171, 178, 191);text-size-adjust: none;min-width: 400px;background: none 0% 0% / auto repeat scroll padding-box border-box rgb(40, 44, 52);font-weight: 400;" data-wx-hl-code="public class FloatTest {&lt;br/&gt; public static void main(String[] args) {&lt;br/&gt; float f1 = 6.6f;&lt;br/&gt; float f2 = 1.3f;&lt;br/&gt; System.out.println(f1 + f2);&lt;br/&gt; } &lt;br/&gt;}" data-wx-hl-lang="Java" data-wx-hl-style="atom-one-dark"><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span style="color: rgb(230, 192, 123);font-weight: 400;font-style: normal;">FloatTest</span> </span>{<br> <span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">static</span> <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">void</span> <span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">main</span><span style="font-weight: 400;font-style: normal;">(String[] args)</span> </span>{<br> <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">float</span> f1 = <span style="color: rgb(209, 154, 102);font-weight: 400;font-style: normal;">6.6f</span>;<br> <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">float</span> f2 = <span style="color: rgb(209, 154, 102);font-weight: 400;font-style: normal;">1.3f</span>;<br> System.out.println(f1 + f2);<br> }<br>}</code></pre> <p><br></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">结果:7.8999996 和自己口算的值竟然不一样</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <figure style="max-width: 100%;color: inherit;font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;font-size: inherit;white-space: normal;background-color: rgb(255, 255, 255);line-height: inherit;box-sizing: border-box !important;overflow-wrap: break-word !important;"> <img title="" data-type="jpeg" data-ratio="1.1473214285714286" data-w="224" src="/upload/873554cfc26317ec79a713330b19a2c6.jpg" style="margin-right: auto;margin-left: auto;font-size: inherit;color: inherit;line-height: inherit;display: block;box-sizing: border-box !important;overflow-wrap: break-word !important;width: 224px !important;visibility: visible !important;"> </figure> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">计算机只认识0和1,所有类型的计算首先会转化为二进制的计算。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h3 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">从计算机二进制角度计算 6.6 + 1.3 的过程</span></strong></span></h3> <p><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;"><br></span></strong></span></p> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">float底层存储</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">计算是由</span> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247491744&idx=3&sn=cddccdabe0d3892c4817dbd03229e647&chksm=eb506596dc27ec80c6335412cb031661ad3afed9dc1793be89ee835a1062e7a3b08f5b8e9c2c&scene=21#wechat_redirect" textvalue="CPU" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">CPU</span></a> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">来完成的,</span> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247491744&idx=3&sn=cddccdabe0d3892c4817dbd03229e647&chksm=eb506596dc27ec80c6335412cb031661ad3afed9dc1793be89ee835a1062e7a3b08f5b8e9c2c&scene=21#wechat_redirect" textvalue="CPU" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">CPU</span></a> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">表示浮点数由三部分组成 分为三个部分,符号位(sign),指数部分(exponent)和有效部分(fraction, mantissa)。其中float总共占用32位,符号位,指数部分,有效部分各占1位,8位,23位。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <img data-backh="99" data-backw="578" data-ratio="0.17250922509225092" data-type="png" data-w="1084" src="/upload/7e69ec3940efd8f22360dca9deddc411.png" style="border-radius: 3px;width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;height: auto;"> </section> <h4 style="line-height: 1.5em;"><br></h4> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">二进制的转化</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">对于实数,转化为二进制分为两部分,第一部分整数部分,第二部分是小数部分。整数部分计算二进制大家都很熟悉。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h6 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">整数部分的计算:6转化为二进制</span></strong></span></h6> <h6 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h6> <section style="line-height: 1.5em;"> <img class="rich_pages" data-backh="290" data-backw="578" data-ratio="0.5011820330969267" data-s="300,640" data-type="png" data-w="846" src="/upload/dc36babaa441dd61c03f714a50372ad1.png" style="border-radius: 3px;width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;height: auto;"> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">所以6最终的二进制为110</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h6 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">小数部分的计算</span></strong></span></h6> <h6 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h6> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">将小数乘以2,取整数部分作为二进制的值,然后再将小数乘以2,再取整数部分,以此往复循环。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h6 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">0.6转化为二进制</span></strong></span></h6> <h6 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h6> <section style="line-height: 1.5em;"> <img class="rich_pages" data-backh="425" data-backw="578" data-ratio="0.7355769230769231" data-s="300,640" data-type="png" data-w="832" src="/upload/35de3c76b7ae8473d47705b30d8048c7.png" style="border-radius: 3px;width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;height: auto;"> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">…进入循环,循环体为1001 所以0.6转化为二进制为0.10011001… 6.6转化为二进制为110.10011001…<br style="max-width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">规约化</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">通过规约化将小数转为规约形式,类似科学计数法,就是保证小数点前面有一个有效数字。在二进制里面,就是保证整数位是一个1。110.10011001规约化为:1.1010011001*2^2。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">指数偏移值</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">指数偏移值 = 固定值 + 规约化的指数值 固定值=2^(e-1)-1,其中的e为存储指数部分的比特位数,前面提到的float为8位。所以float中规定化值为127 6.6的二进制值规约化以后为1.1010011001*2^2,指数是2,所以偏移值就是127+2=129,转换为二进制就是10000001。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">拼接6.6</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">6.6为正数,符号位为0,指数部分为偏移值的二进制10000001,有效部分为规约形式的小数部分,取小数的前23位即10100110011001100110011,最后拼接到一起即 01000000110100110011001100110011。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">到这里已经大致可以知道float为什么不精确了,首先在存储的时候就会造成精度损失了,在这里小数部分的二进制是循环的,但是仍然只能取前23位。double造成精度损失的原因也是如此。推荐阅读:</span> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247484834&idx=1&sn=ea4af7434a399f6433d3a0ae3aac2d05&chksm=eb538094dc240982f3793e54918b128aa4b683b995ac33dfc5c45579422e24bf5fcef3e4226b&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">金融系统中正确的金额计算及存储方式</span></a> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h4 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">求和</span></strong></span></h4> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">原来如此</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <img data-backh="578" data-backw="578" data-ratio="1" data-type="jpeg" data-w="953" src="/upload/97092c87c497cf05855b6ba52508202b.jpg" style="border-radius: 3px;width: 100%;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;height: auto;"> </section> <h3 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></h3> <h3 style="line-height: 1.5em;"><span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">不能使用float那用什么类型存储金额?</span></strong></span></h3> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">使用int 数据库存储的是金额的分值,显示的时候在转化为元。</span> <a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247492998&idx=3&sn=c6921551c7cc4e51bbf58fc9fb46cfd4&chksm=eb5060b0dc27e9a66c611cde7410116af237b736b9fa3c2dd009654714d41e7df71bd64fa04b&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2" hasload="1" style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">Java中的运算神器BigDecimal,</span></a> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">这篇也推荐看下。</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">使用decimal mysql中decimal存储类型的使用</span> </section> <pre style="overflow-x: auto;"><code style="font-size: 0.85em;font-family: Consolas, Menlo, Courier, monospace;margin: 0px 0.15em;white-space: pre;overflow: auto;display: block;padding: 0.5em;color: rgb(171, 178, 191);text-size-adjust: none;min-width: 400px;font-weight: 400;background: none 0% 0% / auto repeat scroll padding-box border-box rgb(40, 44, 52);" data-wx-hl-code="column_name decimal(P,D); " data-wx-hl-lang="Java" data-wx-hl-style="atom-one-dark"><span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;">column_name <span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">decimal</span><span style="font-weight: 400;font-style: normal;">(P,D)</span></span>;</code></pre> <p><br></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">D:代表小数点后的位数 P:有效数字数的精度,小数点也算一位 测试例子 数据表的创建:</span> </section> <pre style="overflow-x: auto;"><code style="font-size: 0.85em;font-family: Consolas, Menlo, Courier, monospace;margin: 0px 0.15em;white-space: pre;overflow: auto;display: block;padding: 0.5em;color: rgb(171, 178, 191);text-size-adjust: none;min-width: 400px;font-weight: 400;background: none 0% 0% / auto repeat scroll padding-box border-box rgb(40, 44, 52);" data-wx-hl-code="CREATE TABLE " test_decimal="test_decimal" amp="amp" int="int" not="not" null="null" amount="amount" decimal="decimal" engine="InnoDB" default charset="utf8mb4"" data-wx-hl-lang="Java" data-wx-hl-style="atom-one-dark">CREATE TABLE `test_decimal` (<br> `id` <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">int</span>(<span style="color: rgb(209, 154, 102);font-weight: 400;font-style: normal;">11</span>) NOT NULL,<br> `amount` decimal(<span style="color: rgb(209, 154, 102);font-weight: 400;font-style: normal;">10</span>,<span style="color: rgb(209, 154, 102);font-weight: 400;font-style: normal;">2</span>) NOT NULL<br>) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4</code></pre> <p><br></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">对应的DAO层代码:TestDecimalDao.java</span> </section> <pre style="overflow-x: auto;"><code style="font-size: 0.85em;font-family: Consolas, Menlo, Courier, monospace;margin: 0px 0.15em;white-space: pre;overflow: auto;display: block;padding: 0.5em;color: rgb(171, 178, 191);text-size-adjust: none;min-width: 400px;font-weight: 400;background: none 0% 0% / auto repeat scroll padding-box border-box rgb(40, 44, 52);" data-wx-hl-code="/** &lt;br/&gt; * @description dao层 &lt;br/&gt; * &lt;br/&gt; * @author JoyHe &lt;br/&gt; * @date 2018/11/05 &lt;br/&gt; * @version 1.0 &lt;br/&gt; */ &lt;br/&gt;@Repository &lt;br/&gt;public interface TestDecimalDao { &lt;br/&gt; @Select("select * from test_decimal where id = #{id}") &lt;br/&gt; TestDecimal getTestDecimal(int id); &lt;br/&gt;} " data-wx-hl-lang="Java" data-wx-hl-style="atom-one-dark"><span style="color: rgb(92, 99, 112);font-weight: 400;font-style: italic;">/**<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@description</span> dao层<br> *<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@author</span> JoyHe<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@date</span> 2018/11/05<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@version</span> 1.0<br> */</span> <br><span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">@Repository</span> <br><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">interface</span> <span style="color: rgb(230, 192, 123);font-weight: 400;font-style: normal;">TestDecimalDao</span> </span>{<br> <span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">@Select</span>(<span style="color: rgb(152, 195, 121);font-weight: 400;font-style: normal;">"select * from test_decimal where id = #{id}"</span>)<br> <span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;">TestDecimal <span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">getTestDecimal</span><span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;">(<span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">int</span> id)</span></span>;<br>}</code></pre> <p><br></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">测试类:TestDecimalDaoTest.java </span> </section> <pre style="overflow-x: auto;"><code style="font-size: 0.85em;font-family: Consolas, Menlo, Courier, monospace;margin: 0px 0.15em;white-space: pre;overflow: auto;display: block;padding: 0.5em;color: rgb(171, 178, 191);text-size-adjust: none;min-width: 400px;font-weight: 400;background: none 0% 0% / auto repeat scroll padding-box border-box rgb(40, 44, 52);" data-wx-hl-code="/** &lt;br/&gt; * @description 测试类 &lt;br/&gt; * &lt;br/&gt; * @author JoyHe &lt;br/&gt; * @date 2018/11/05 &lt;br/&gt; * @version 1.0 &lt;br/&gt; */ &lt;br/&gt;public class TestDecimalDaoTest extends BaseTest { &lt;br/&gt; @Resource &lt;br/&gt; private TestDecimalDao testDecimalDao; &lt;br/&gt;&lt;br/&gt; @Test &lt;br/&gt; public void test() { &lt;br/&gt; TestDecimal testDecimal1 = testDecimalDao.getTestDecimal(1); &lt;br/&gt; TestDecimal testDecimal2 = testDecimalDao.getTestDecimal(2); &lt;br/&gt; BigDecimal result = testDecimal1.getAmount().add(testDecimal2.getAmount()); &lt;br/&gt; System.out.println(result.floatValue()); &lt;br/&gt; } &lt;br/&gt;} " data-wx-hl-lang="Java" data-wx-hl-style="atom-one-dark"><span style="color: rgb(92, 99, 112);font-weight: 400;font-style: italic;">/**<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@description</span> 测试类<br> *<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@author</span> JoyHe<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@date</span> 2018/11/05<br> * <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: italic;">@version</span> 1.0<br> */</span> <br><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">class</span> <span style="color: rgb(230, 192, 123);font-weight: 400;font-style: normal;">TestDecimalDaoTest</span> <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">extends</span> <span style="color: rgb(230, 192, 123);font-weight: 400;font-style: normal;">BaseTest</span> </span>{<br> <span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">@Resource</span> <br> <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">private</span> TestDecimalDao testDecimalDao;<br><br> <span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">@Test</span> <br> <span style="color: rgb(171, 178, 191);font-weight: 400;font-style: normal;"><span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">public</span> <span style="color: rgb(198, 120, 221);font-weight: 400;font-style: normal;">void</span> <span style="color: rgb(97, 174, 238);font-weight: 400;font-style: normal;">test</span><span style="font-weight: 400;font-style: normal;">()</span> </span>{<br> TestDecimal testDecimal1 = testDecimalDao.getTestDecimal(<span style="color: rgb(209, 154, 102);font-weight: 400;font-style: normal;">1</span>);<br> TestDecimal testDecimal2 = testDecimalDao.getTestDecimal(<span style="color: rgb(209, 154, 102);font-weight: 400;font-style: normal;">2</span>);<br> BigDecimal result = testDecimal1.getAmount().add(testDecimal2.getAmount());<br> System.out.println(result.floatValue());<br> }<br>}</code></pre> <p><span style="font-size: 15px;text-align: left;"><br></span></p> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">说明:jdbcType为decimal转化为javaType为BigDecimal 测试结果:</span> </section> <section style="line-height: 1.5em;"> <img data-backh="145" data-backw="578" data-ratio="0.25161290322580643" data-type="png" data-w="1240" src="/upload/a1332be9c0b5db6e7c765d520b3c407c.png" style="border-radius: 3px;width: 677px;box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;"> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="color: rgb(171, 25, 66);"><strong><span style="font-size: 15px;letter-spacing: normal;">是符合预期的7.9</span></strong></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <h3 style="line-height: 1.5em;"><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">使用decimal存储类型的缺点</span></h3> <p><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span></p> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">1、占用存储空间。</span></strong> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">浮点类型在存储同样范围的值时,通常比decimal使用更少的空间</span> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;"><br></span> </section> <section style="line-height: 1.5em;"> <strong><span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">2、使用decimal计算效率不高 </span></strong> </section> <section style="line-height: 1.5em;"> <br> </section> <section style="line-height: 1.5em;"> <span style="font-size: 15px;color: rgb(0, 0, 0);letter-spacing: normal;">因为使用decimal时间和空间开销较大,选用int作为数据库存储格式比较合适,可以同时避免浮点存储计算的不精确和decimal的缺点。对于存储数值较大或者保留小数较多的数字,数据库存储结构可以选择bigint。</span> </section> <section style="line-height: 1.5em;"> <br> </section> <section donone="shifuMouseDownCard('shifu_c_030')" label="Copyright Reserved by PLAYHUDONG." style="text-align: start;white-space: normal;margin-top: 1em;margin-bottom: 1em;caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);border-width: 0px;border-style: initial;border-color: initial;"> <section style="margin-left: 1em;line-height: 1.4;"> <span style="padding: 3px 8px;border-top-left-radius: 4px;border-top-right-radius: 4px;border-bottom-right-radius: 4px;border-bottom-left-radius: 4px;color: rgb(255, 255, 255);background-color: rgb(255, 105, 31);font-family: inherit;text-align: inherit;text-decoration: inherit;font-size: 16px;">推荐阅读</span> <span style="margin-left: 4px;padding: 3px 8px;border-top-left-radius: 1.2em;border-top-right-radius: 1.2em;border-bottom-right-radius: 1.2em;border-bottom-left-radius: 1.2em;color: rgb(255, 255, 255);line-height: 1.2;background-color: rgb(204, 204, 204);font-family: inherit;text-align: inherit;text-decoration: inherit;border-color: rgb(249, 110, 87);font-size: 12px;">点击标题可跳转</span> </section> <section style="margin-top: -11px;padding: 22px 16px 16px;border-width: 1px;border-style: solid;border-color: rgb(255, 105, 31);color: rgb(51, 51, 51);font-size: 1em;font-family: inherit;text-align: inherit;text-decoration: inherit;"> <p><span style="font-size: 12px;font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651487353&idx=1&sn=596ba717693ec75bce47178284f7c52f&chksm=bd2510068a529910510133b428460a1b1668c917f41edb45e41a0936f964f340e230bda28c9c&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">JAVA 线上故障排查完整套路!牛掰!</a><br></span></p> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651487024&idx=1&sn=605865a751409f5e83d4ad281197d930&chksm=bd25174f8a529e59f38b8d70cd4c375b89fa2cf8e10669a77f1e5a304641ea3b19d84ea5029c&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">记一次 JAVA 的内存泄露分析</a><br></span></p> <p><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-decoration: underline;"><a target="_blank" href="http://mp.weixin.qq.com/s?__biz=MjM5NzMyMjAwMA==&mid=2651486970&idx=1&sn=5f04a331f9db9d3c0d21064e491cd5fd&chksm=bd2516858a529f93a432b11ad7945d4f63153e9fb678400a1e3e2e117b4b6b784e02c86c9d35&scene=21#wechat_redirect" data-itemshowtype="0" tab="innerlink" data-linktype="2">用 Java 写一个植物大战僵尸简易版</a></span><span style="font-family: -apple-system-font, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 12px;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);"><br></span></p> </section> </section> <p style="caret-color: rgb(0, 0, 0);color: rgb(0, 0, 0);text-align: start;white-space: normal;"><br></p> <p style="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;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="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;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="white-space: normal;max-width: 100%;min-height: 1em;letter-spacing: 0.544px;background-color: rgb(255, 255, 255);text-align: center;box-sizing: border-box !important;overflow-wrap: break-word !important;"><img data-ratio="0.9166666666666666" data-s="300,640" data-type="jpeg" data-w="600" width="auto" src="/upload/899866149276fa5fddb73c61ae04be64.jpg" style="box-sizing: border-box !important;overflow-wrap: break-word !important;visibility: visible !important;width: 600px !important;"></p> <p style="text-align: right;"><span style="font-size: 14px;text-align: right;">好文章,我</span><span style="font-size: 14px;text-align: right;color: rgb(255, 41, 65);">在看</span><span style="font-size: 14px;text-align: right;">❤️</span></p>
作者:微信小助手
<section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="font-size: 16px;color: black;padding-right: 10px;padding-left: 10px;line-height: 1.6;letter-spacing: 0px;word-break: break-word;overflow-wrap: break-word;text-align: left;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-top: -10px;"> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">大家好,我是 Guide 哥,一个三观比主角还正的技术人。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">今天推荐几个 Java 项目快速开发脚手架,解放双手 ✋ 从现在开始。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">以下推荐项目都是码云上的优质项目,并且都是项目快速开发脚手架,代码质量什么的无法保证能有多好,毕竟很多也是个人开发,或多或少也有个人色彩影响。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">不过既然开源出来,这么多人参与,一般情况下项目整体质量可以说是非常不错的了。另外,下面推荐的项目几乎都是码云上面选出来的最有价值的开源项目。后面,可能会单独再推荐一期 Github 上的 Java 项目快速开发脚手架。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">想要获取更多开源项目资源?欢迎关注我的 awesome-java(Github 上非常棒的 Java 开源项目集合),地址:<strong><span style="color: rgb(77, 168, 238);">https://github.com/Snailclimb/awesome-java </span></strong>。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">概览</strong> :</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> Guns </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> pig </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> RuoYi </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> Jeecg-boot </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> iBase4J </section></li> </ol> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);margin-bottom: 30px;color: rgb(89, 89, 89);"><span style="display: none;"></span><span style="display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">Guns</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">推荐指数</strong> :⭐⭐⭐⭐⭐</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>简介<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">我在上大学的时候就了解和接触过了这个项目,当时我还是一个 Spring 入门不太久的小菜鸟。一晃,不经意间已经过去快 3 年了。</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">采用主流框架</strong> :基于 Spring Boot2.0+版本开发,并且支持 Spring Cloud Alibaba 微服务。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">功能齐全</strong> :包含系统管理,代码生成,多数据库适配,SSO 单点登录,工作流,短信,邮件发送,OAuth2 登录,任务调度,持续集成,docker 部署等功能; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">提供了企业版</strong> :企业版功能更多,并且提供了完善的开发文档,开发 demo,快速入门。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">相关地址:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目地址 : <strong><span style="color: rgb(77, 168, 238);">https://gitee.com/stylefeng/guns</span></strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目官网 : <strong><span style="color: rgb(77, 168, 238);">https://www.stylefeng.cn/</span></strong> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">另外,这个项目还提供了视频教你如何使用,地址:<strong><span style="color: rgb(77, 168, 238);">https://www.bilibili.com/video/av56718207 </span></strong>。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>推荐理由<span style="display: none;"></span></h3> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目技术主流,唯一缺点是企业版和微服务版需要单独购买。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 社区活跃。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目功能完善,满足企业绝大部分场景开发需求,并且额外提供了持续集成,docker 部署等功能。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ...... </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>适合场景<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">适合企业后台管理网站的快速开发场景,不论是对于单体和微服务都有支持。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>项目展示<span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5563076923076923" src="/upload/5c788bab13a0dfd4dd4473cba5f99488.png" data-type="png" data-w="3250" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5573366214549939" src="/upload/22d2891dec509e766d18e90b5a3ddefd.png" data-type="png" data-w="3244" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);margin-bottom: 30px;color: rgb(89, 89, 89);"><span style="display: none;"></span><span style="display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">pig</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">推荐指数</strong> :⭐⭐⭐⭐⭐</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>简介<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">这个项目之前就推荐过几次,你可以在这个视频:<strong><span style="color: rgb(77, 168, 238);">https://www.bilibili.com/video/BV1b7411N7Qt </span></strong>中找到。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">根据项目官网,简单说下这个项目:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 基于 Spring Cloud Hoxton 、Spring Boot 2.2、 OAuth2 的 RBAC 权限管理系统 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 基于数据驱动视图的理念封装 element-ui,即使没有 vue 的使用经验也能快速上手 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提供对常见容器化支持 Docker、Kubernetes、Rancher2 支持 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提供 lambda 、stream api 、webflux 的生产实践 </section></li> </ol> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.6666666666666666" src="/upload/f0aa794778a0c0c8198b29648667d06b.png" data-type="png" data-w="1128" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">相关地址</strong>:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目地址: <strong><span style="color: rgb(77, 168, 238);">https://gitee.com/log4j/pig</span></strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 官网地址: <strong><span style="color: rgb(77, 168, 238);">https://pig4cloud.com/</span></strong> </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>推荐理由<span style="display: none;"></span></h3> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 社区活跃; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提供了 Spring Cloud Hoxton & Alibaba 的微服务版本; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 权限管理做得不错! </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 功能完全开源! </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 支持第三方系统比如 guns、renren 接入 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ...... </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>适合场景<span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.4473684210526316" src="/upload/c9771a8c4382ff0ed40f8d464ade4e27.png" data-type="png" data-w="2356" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>项目展示<span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5483076923076923" src="/upload/faef0ca6be750b27250ed53c574dd1.png" data-type="png" data-w="3250" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5507068223724647" src="/upload/28bbf930e7d726f41decc9d337e849ab.png" data-type="png" data-w="3254" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);margin-bottom: 30px;color: rgb(89, 89, 89);"><span style="display: none;"></span><span style="display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">RuoYi</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">推荐指数</strong> :⭐⭐⭐⭐</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>简介<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">项目名字是作者还未出生的女儿,看到之后很感动!</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">RuoYi 一款基于基于 SpringBoot 的权限管理系统 易读易懂、界面简洁美观,直接运行即可用 。</p> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">作者是这样介绍这个项目的:</p> <blockquote data-tool="mdnice编辑器" style="font-size: 0.9em;overflow: auto;background: rgba(0, 0, 0, 0.05);margin-bottom: 20px;margin-top: 20px;padding-top: 10px;padding-right: 10px;padding-bottom: 10px;line-height: 1.8;border-width: initial;border-style: none;border-color: initial;color: rgb(136, 136, 136);"> <span style="color: rgb(85, 85, 85);font-size: 4em;font-family: Arial, serif;line-height: 1em;font-weight: 700;">“</span> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;display: inline;">一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适的。于是利用空闲休息时间开始自己写了一套后台系统。如此有了若依。她可以用于所有的 Web 应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。</p> <p style="font-size: 16px;padding-top: 8px;padding-bottom: 8px;color: black;line-height: 26px;display: inline;">性别男,若依是给还没有出生女儿取的名字(寓意:你若不离不弃,我必生死相依)</p> </blockquote> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">相关网站</strong> :</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目地址 : <strong><span style="color: rgb(77, 168, 238);">https://gitee.com/y_project/RuoYi</span></strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 文档地址 : <strong><span style="color: rgb(77, 168, 238);">http://doc.ruoyi.vip/</span></strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 官网地址: <strong><span style="color: rgb(77, 168, 238);">http://ruoyi.vip/</span></strong> </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>推荐理由<span style="display: none;"></span></h3> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提供了多种版本:单体、前后端分离、微服务(即将开源) </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提供的功能齐全,覆盖大部分场景需求 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提供的文档丰富便于上手和学习 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 生态系统丰富提供了多种版本 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 采用主流框架比如 SpringBoot、Shiro、Thymeleaf、Vue、Bootstrap </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ...... </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>适合场景<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">她可以用于所有的 Web 应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>项目展示<span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5622254758418741" src="/upload/5b53b6ade9702783060134437c2b6f2f.png" data-type="png" data-w="1366" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);margin-bottom: 30px;color: rgb(89, 89, 89);"><span style="display: none;"></span><span style="display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">Jeecg-boot</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">推荐指数</strong> :⭐⭐⭐</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>简介<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">这个项目同样在我上大学那会就很火了!简单从下面说几个方面介绍 Jeecg-boot 吧!</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">低代码</strong> :JeecgBoot 是一款基于代码生成器的 J2EE 低代码快速开发平台。强大的代码生成器让前后端代码一键生成,无需写任何代码! </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">采用主流框架</strong> :整体采用现在流行的前后端分离架构:后端框架为主流的 SpringBoot 2.x,前端为主流的 Ant Design&Vue。另外,还用到了 Mybatis-plus 数据库层面的框架,以及 Shiro 和 JWT 做身份认证和权限管理。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">整体灵活实用</strong> :简单功能由 Online Coding 配置实现,帮助 Java 项目解决 70%重复工作,复杂功能由代码生成器生成进行手工 Merge。让开发更关注业务逻辑,既能快速提高开发效率,帮助公司节省成本,同时又不失灵活性。 </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">相关地址:</strong></p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目地址: <strong><span style="color: rgb(77, 168, 238);">https://gitee.com/jeecg/jeecg-boot</span></strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 在线演示 : <strong><span style="color: rgb(77, 168, 238);">http://boot.jeecg.com</span></strong> </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 技术官网: <strong><span style="color: rgb(77, 168, 238);">http://www.jeecg.com</span></strong> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">整个项目的技术架构如下图所示,README 文档已经贴好了,我就直接复制过来了。</p> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="1.2528" src="/upload/b213eb411bdd24d6b911a9bb9b4a97cc.png" data-type="png" data-w="1250" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>推荐理由<span style="display: none;"></span></h3> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 采用主流框架,前后端分离,对开发比较友好; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 用户管理和权限权利模块做的非常好,满足绝大部分人员管理场景的需求。权限控制采用 RBAC(Role-Based Access Control,基于角色的访问控制) ,支持菜单动态路由。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 提供了 Excel 导入导出、报表工具等必备功能。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 自带消息中心,支持短信、邮件、微信推送等等。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 页面校验自动生成(必须输入、数字校验、金额校验、时间空间等); </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 平台 UI 强大,实现了移动自适应,无需再为移动端适配; </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ...... </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>适合场景<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">Jeecg-Boot 快速开发平台,可以应用在任何 J2EE 项目的开发中,尤其适合企业信息管理系统(MIS)、内部办公系统(OA)、企业资源计划系统(ERP)、客户关系管理系统(CRM)等,其半智能手工 Merge 的开发方式,可以显著提高开发效率 70%以上,极大降低开发成本。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>项目展示<span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5602223594811612" src="/upload/1488788c68acd79a995c795df8d95c65.png" data-type="png" data-w="3238" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.5596555965559655" src="/upload/a76c694854e5eb98bb9df3feb96d0a07.png" data-type="png" data-w="3252" style="display: block;margin-right: auto;margin-left: auto;"> </figure> <h2 data-tool="mdnice编辑器" style="margin-top: 30px;font-weight: bold;font-size: 22px;border-bottom: 2px solid rgb(89, 89, 89);margin-bottom: 30px;color: rgb(89, 89, 89);"><span style="display: none;"></span><span style="display: inline-block;border-bottom: 2px solid rgb(89, 89, 89);">iBase4J</span></h2> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);"><strong style="color: rgb(71, 193, 168);">推荐指数</strong> :⭐⭐</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>简介<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">简单来说:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">分布式架构</strong> :iBase4J 是 Java 语言的分布式系统架构。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">Maven 模块化管理</strong> :使用 Maven 对项目进行模块化管理,提高项目的易开发性、扩展性。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> <strong style="color: rgb(71, 193, 168);">子系统扩展性强</strong> :子系统之间使用 Dubbo 或 MQ 进行通信。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ...... </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">相关地址:</p> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 项目地址: <strong><span style="color: rgb(77, 168, 238);">https://gitee.com/iBase4J/iBase4J</span></strong> </section></li> </ol> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">技术选型如下:</p> <ul data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 核心框架:Sring boot + Spring Framework + Dubbo + ibase4j-common </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 安全框架:Apache Shiro </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 任务调度:Spring + Quartz </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 持久层框架:MyBatis + MyBatis-Plus </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 数据库连接池:Alibaba Druid </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 缓存框架:Redis </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 会话管理:Spring-Session </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 日志管理:SLF4J、Log4j2 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 前端框架:Angular JS + Bootstrap + Jquery </section></li> </ul> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>推荐理由<span style="display: none;"></span></h3> <ol data-tool="mdnice编辑器" style="margin-top: 8px;margin-bottom: 8px;padding-left: 25px;" class="list-paddingleft-2"> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 分布式架构,但是用的是 Dubbo,如果有 Spring Cloud 版本就好了。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 支持 QQ、微信、新浪微博第三方登录。 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> 自带 excel 导入导出,汉字转拼音,身份证号码验证,数字转大写人民币,FTP/SFTP/fastDFS 上传下载,发送邮件,redis 缓存,加密等等工具类 </section></li> <li> <section style="margin-top: 5px;margin-bottom: 5px;line-height: 26px;color: rgb(1, 1, 1);"> ...... </section></li> </ol> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>适合场景<span style="display: none;"></span></h3> <p data-tool="mdnice编辑器" style="padding-top: 8px;padding-bottom: 8px;line-height: 26px;color: rgb(89, 89, 89);">分布式企业管理系统的场景。</p> <h3 data-tool="mdnice编辑器" style="margin-top: 30px;margin-bottom: 15px;font-weight: bold;font-size: 20px;color: rgb(89, 89, 89);"><span style="display: none;"></span>项目展示<span style="display: none;"></span></h3> <figure data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;"> <img data-ratio="0.49765258215962443" src="/upload/af4dce15c709c1f463133c93fe59f4df.png" data-type="png" data-w="1917" style="display: block;margin-right: auto;margin-left: auto;"> </figure> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: -10px;padding-right: 10px;padding-left: 10px;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0px;text-align: left;white-space: normal;color: rgb(62, 62, 62);background-color: rgb(255, 255, 255);line-height: 1.6;word-break: break-word;overflow-wrap: break-word;"> <section data-role="outer" label="Powered by 135editor.com"> <section data-tools="135编辑器" data-id="97823"> <section style="margin: 10px auto;width: 70px;"> <br> </section> <section style="margin: 10px auto;width: 70px;"> <img data-ratio="0.39285714285714285" src="/upload/e6c763c1663007073ae0e41d9eb1024d.png" data-type="png" data-w="112" data-width="100%" style="width: 70px;display: block;"> </section> </section> </section> </section> <section data-tool="mdnice编辑器" data-website="https://www.mdnice.com" style="margin-top: -10px;padding-right: 10px;padding-left: 10px;color: black;font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;letter-spacing: 0px;text-align: left;white-space: normal;background-color: rgb(255, 255, 255);line-height: 1.6;word-break: break-word;overflow-wrap: break-word;"> <section data-tools="135编辑器" data-id="92648"> <section style="margin-top: 15px;margin-right: auto;margin-left: auto;"> <section style="margin-right: auto;margin-left: auto;display: -webkit-flex;justify-content: center;"> <section style="margin-top: -14px;padding-right: 5px;padding-left: 5px;width: 55px;background-image: initial;background-position: initial;background-size: initial;background-repeat: initial;background-attachment: initial;background-origin: initial;background-clip: initial;"> <br> </section> </section> </section> </section> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;letter-spacing: 0.2em;font-size: 14px;word-spacing: 0.1em;"><span style="word-spacing: 0.1em;color: rgb(74, 74, 74);font-size: 16px;letter-spacing: 0.544px;">我的 75k Star 开源项目 JavaGuide 总结而成的PDF版本的</span><strong><span style="word-spacing: 0.1em;font-size: 16px;letter-spacing: 0.544px;color: rgb(61, 170, 214);"><a target="_blank" href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486324&idx=1&sn=e8b690ddaedabc486bd399310105aad3&chksm=cea244bff9d5cda9a627fa65235be09e7b089e92cf49c0eb0ceb35b39bbed86c1fab0125f5af&token=1745528586&lang=zh_CN&scene=21#wechat_redirect" textvalue="《JavaGuide面试突击版》" tab="innerlink" data-linktype="2">《JavaGuide面试突击版》</a></span></strong><span style="word-spacing: 0.1em;color: rgb(74, 74, 74);font-size: 16px;letter-spacing: 0.544px;">,公众号后台回复“</span><strong><span style="word-spacing: 0.1em;font-size: 16px;letter-spacing: 0.544px;color: rgb(61, 170, 214);">面试突击</span></strong><span style="word-spacing: 0.1em;color: rgb(74, 74, 74);font-size: 16px;letter-spacing: 0.544px;">”即可获取最新版本!安排!</span></p> <p data-tool="mdnice编辑器" style="margin: 10px;padding-top: 8px;padding-bottom: 8px;line-height: 1.75;letter-spacing: 0.2em;font-size: 14px;word-spacing: 0.1em;"><span style="font-family: PingFangSC-Light;letter-spacing: 2.8px;word-spacing: 1.4px;"></span><img data-backh="326" data-backw="518" data-ratio="0.6287037037037037" src="/upload/8cceb9ea994a531f83dfdc26a7d53fdc.jpg" data-type="jpeg" data-w="1080" style="margin-right: auto;margin-bottom: 25px;margin-left: auto;word-spacing: 1.4px;color: rgb(63, 63, 63);font-size: 16px;letter-spacing: 0.544px;display: block;width: 518px;border-radius: 4px;"></p> <section data-role="outer" label="Powered by 135editor.com"> <section data-tools="135编辑器" data-id="95098"> <section style="margin: 1em auto;"> <section style="display: flex;justify-content: center;align-items: center;"> <section data-width="50%" style="width: 224.672px;height: 1px;background: rgb(203, 203, 239);overflow: hidden;"> <br> </section> <section style="margin-right: 4px;margin-left: 4px;width: 125px;"> <img data-ratio="0.37423312883435583" src="/upload/1478f46b3ef0456859a11fecc0a5479a.gif" data-type="gif" data-w="163" style="width: 125px;display: block;"> </section> <section data-width="50%" style="width: 224.672px;height: 1px;background: rgb(203, 203, 239);overflow: hidden;"> <br> </section> </section> </section> </section> </section> </section> <p><br></p> <p><br></p> <section data-from="xmt-recommend" data-tools="新媒体排版"> <a href="http://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486968&idx=1&sn=7cc1bc123228121636eb9b4008a4e900&chksm=cea24233f9d5cb2535879ecec5e89338d3d7cd49981444fa51be7e43c54310b60f4bb11e7d2a&scene=21#wechat_redirect" target="_blank" style="width:100%;" data-linktype="2"> <section style="white-space:nowrap;text-align:left;text-decoration:none;display:block;margin:16px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;box-shadow:rgba(0, 0, 0, 0.15) 0 0 12px 0;height:154px;"> <section style="margin:0;bottom:0;-webkit-box-sizing:border-box;box-sizing:border-box;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;width:100%;height:154px;"> <section class="h5_image_link" style="width: 100%;height: 154px;background-size: cover;background-position: 50% center;background-image: url("https://mmbiz.qpic.cn/mmbiz_jpg/iaIdQfEric9TzZpoplUhubTysrme5Syb5scbyIJftE2zbmEEiaia5X3tE95NBr3pIPVp1flFF8Nf1pLkUdeAU9oXzQ/640?wx_fmt=jpeg");display: inherit;font-size: inherit;z-index: -1;"> </section> <section style="bottom:0;padding:5px 16px;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;background-color:rgba(0,0,0,.5);color:#fff;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:16px;margin-top:-35px;"> 优质文章分类整理|Guide哥直呼:看了这些技术文章我之后飘了~ </section> </section> </section></a> </section> <section data-from="xmt-recommend" data-tools="新媒体排版"> <a href="http://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486967&idx=1&sn=4d10a857f1125db7b3a58992d9cc073a&chksm=cea2423cf9d5cb2a60e567211bcfc37387a96657d05a1563f07e8b437d5e0071f07f2de9fd0c&scene=21#wechat_redirect" target="_blank" style="width:100%;" data-linktype="2"> <section style="white-space:nowrap;text-align:left;text-decoration:none;display:block;margin:16px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;box-shadow:rgba(0, 0, 0, 0.15) 0 0 12px 0;height:154px;"> <section style="margin:0;bottom:0;-webkit-box-sizing:border-box;box-sizing:border-box;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;width:100%;height:154px;"> <section class="h5_image_link" style="width: 100%;height: 154px;background-size: cover;background-position: 50% center;background-image: url("https://mmbiz.qpic.cn/mmbiz_jpg/iaIdQfEric9TyqhZNz6UnqV8rpMFFLXa8vEhwdsibXDpGQhF5f2vd8m2SZgj17AzpjHj2VFG0kKnicgC77kftheOhA/640?wx_fmt=jpeg");display: inherit;font-size: inherit;z-index: -1;"> </section> <section style="bottom:0;padding:5px 16px;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;background-color:rgba(0,0,0,.5);color:#fff;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:16px;margin-top:-35px;"> 武汉实录|记Guide哥的一次晚餐所见所感 </section> </section> </section></a> </section> <section data-from="xmt-recommend" data-tools="新媒体排版"> <a href="http://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486938&idx=1&sn=c99ef0233f39a5ffc1b98c81e02dfcd4&chksm=cea24211f9d5cb07fa901183ba4d96187820713a72387788408040822ffb2ed575d28e953ce7&scene=21#wechat_redirect" target="_blank" style="width:100%;" data-linktype="2"> <section style="white-space:nowrap;text-align:left;text-decoration:none;display:block;margin:16px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:4px;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;box-shadow:rgba(0, 0, 0, 0.15) 0 0 12px 0;height:154px;"> <section style="margin:0;bottom:0;-webkit-box-sizing:border-box;box-sizing:border-box;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;width:100%;height:154px;"> <section class="h5_image_link" style="width: 100%;height: 154px;background-size: cover;background-position: 50% center;background-image: url("https://mmbiz.qpic.cn/mmbiz_jpg/iaIdQfEric9TxWKzVAbIedB8n720icmGDzABg31kbYUibrMzeYO4J35yyYI9CXDic98oGsfbr61KD9vmBbk7Hiaa30bA/640?wx_fmt=jpeg");display: inherit;font-size: inherit;z-index: -1;"> </section> <section style="bottom:0;padding:5px 16px;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box;background-color:rgba(0,0,0,.5);color:#fff;-o-text-overflow:ellipsis;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;font-size:16px;margin-top:-35px;"> 面试被问了几百遍的 IoC 和 AOP ,还在傻傻搞不清楚? </section> </section> </section></a> </section> <p style="font-size: 16px;white-space: normal;color: rgb(62, 62, 62);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;widows: 1;word-spacing: 2px;caret-color: rgb(255, 0, 0);background-color: rgb(255, 255, 255);text-align: center;"><img class="rich_pages" data-ratio="0.45818815331010454" data-s="300,640" src="/upload/3e080a01914f7849b65ecf41a0e33320.png" data-type="png" data-w="574"><br></p> <p style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;"><br style="color: rgb(62, 62, 62);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;background-color: rgb(255, 255, 255);"></p> <section data-role="outer" label="Powered by 135editor.com" style="color: rgb(0, 0, 0);font-family: Optima-Regular, Optima, PingFangSC-light, PingFangTC-light, "PingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 16px;text-align: left;white-space: normal;letter-spacing: 0.544px;widows: 1;word-spacing: 2px;caret-color: rgb(255, 0, 0);background-color: rgb(255, 255, 255);"> <section data-tools="135编辑器" data-id="95172"> <section style="display: flex;justify-content: flex-end;align-items: center;"> <section style="display: inline-block;text-align: right;"> <section data-brushtype="text" style="margin-bottom: -15px;color: rgb(63, 63, 63);letter-spacing: 2px;transform: rotate(0deg);"> 好文让朋友知道你“在看” </section> </section> <section style="width: 22px;"> <section style="margin-top: 15px;width: 22px;"> <img data-ratio="1.0377358490566038" src="/upload/c82b6435fb6d21d1bdda03cdcf7b22f5.gif" data-type="gif" data-w="53" data-width="100%" style="width: 22px;display: block;"> </section> </section> </section> </section> </section>