You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

506 lines
239 KiB

<!doctypehtml><html lang=zh-CN><meta charset=UTF-8><meta content=width=device-width name=viewport><meta content=#222 name=theme-color><meta content="Hexo 6.3.0" name=generator><link href=https://fonts.googleapis.com rel=preconnect><link href=https://cdnjs.cloudflare.com rel=preconnect><link href=/images/apple-touch-icon-next.png rel=apple-touch-icon sizes=180x180><link href=/images/favicon-32x32-next.png rel=icon sizes=32x32 type=image/png><link href=/images/favicon-16x16-next.png rel=icon sizes=16x16 type=image/png><link color=#222 href=/images/logo.svg rel=mask-icon><meta content=2X6S9P7CAjXjVvw8YyQR8pCu-B0oEu7O9quLgxXuWyA name=google-site-verification><meta content=dV8JGNzi0c name=baidu-site-verification><script>setTimeout(function(){var d=document.createElement("script");d.setAttribute("data-ad-client","ca-pub-7480618470784058"),d.async=!0,d.src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js",document.body.appendChild(d)},5e3),window.addEventListener?window.addEventListener("load",downloadJsAtOnload,!1):window.attachEvent?window.attachEvent("onload",downloadJsAtOnload):window.onload=downloadJsAtOnload</script><style>:root{--body-bg-color:#f5f7f9;--content-bg-color:#fff;--card-bg-color:#f5f5f5;--text-color:#555;--blockquote-color:#666;--link-color:#555;--link-hover-color:#222;--brand-color:#fff;--brand-hover-color:#fff;--table-row-odd-bg-color:#f9f9f9;--table-row-hover-bg-color:#f5f5f5;--menu-item-bg-color:#f5f5f5;--theme-color:#222;--btn-default-bg:#fff;--btn-default-color:#555;--btn-default-border-color:#555;--btn-default-hover-bg:#222;--btn-default-hover-color:#fff;--btn-default-hover-border-color:#222;--highlight-background:#f3f3f3;--highlight-foreground:#444;--highlight-gutter-background:#e1e1e1;--highlight-gutter-foreground:#555;color-scheme:light}html{line-height:1.15;-webkit-text-size-adjust:100%}details,main{display:block}pre{font-size:1em;overflow:auto;padding:10px;position:relative}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}.table-container,textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}summary{display:list-item}[hidden],template{display:none}::selection{background:#262a30;color:#eee}body,html{height:100%}body{margin:0;background:var(--body-bg-color);box-sizing:border-box;color:var(--text-color);font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-size:1.2em;line-height:2;min-height:100%;position:relative;transition:padding .2s ease-in-out}h1,h2,h3,h4,h5,h6{font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-weight:700;line-height:1.5;margin:30px 0 15px}h1{font-size:1.5em}h2{font-size:1.375em}h3{font-size:1.25em}h4{font-size:1.125em}h5{font-size:1em}h6{font-size:.875em}p{margin:0 0 20px}a{background:0 0;border-bottom:1px solid #999;color:var(--link-color);cursor:pointer;outline:0;text-decoration:none;overflow-wrap:break-word}a:hover{border-bottom-color:var(--link-hover-color);color:var(--link-hover-color)}embed,iframe,img,video{display:block;margin-left:auto;margin-right:auto;max-width:100%}hr{box-sizing:content-box;overflow:visible;background-image:repeating-linear-gradient(-45deg,#ddd,#ddd 4px,transparent 4px,transparent 8px);border:0;height:3px;margin:40px 0}blockquote{border-left:4px solid #ddd;color:var(--blockquote-color);margin:0;padding:0 15px}blockquote cite::before{content:'-';padding:0 5px}dt{font-weight:700}dd{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0;font-size:.875em;margin:0 0 20px;width:100%}tbody tr:nth-of-type(odd){background:var(--table-row-odd-bg-color)}tbody tr:hover{background:var(--table-row-hover-bg-color)}caption,td,th{padding:8px}td,th{border:1px solid #ddd;border-bottom:3px solid #ddd}th{font-weight:700;padding-bottom:10px}td{border-bottom-width:1px}.btn{background:var(--btn-default-bg);border:2px solid var(--btn-default-border-color);border-radius:2px;color:var(--btn-default-color);display:inline-block;font-size:.875em;line-height:2;padding:0 20px;transition:background-color .2s ease-in-out}.btn:hover{background:var(--btn-default-hover-bg);border-color:var(--btn-default-hover-border-color);color:var(--btn-default-hover-color)}.btn+.btn{margin:0 0 8px 8px}.btn .fa-fw{text-align:left;width:1.285714285714286em}.toggle{line-height:0}.toggle .toggle-line{background:#fff;display:block;height:2px;left:0;position:relative;top:0;transition:.4s;width:100%}.toggle .toggle-line:first-child{margin-top:1px}.toggle .toggle-line:not(:first-child){margin-top:4px}.toggle.toggle-arrow :first-child{left:50%;top:2px;transform:rotate(45deg);width:50%}.toggle.toggle-arrow :last-child{left:50%;top:-2px;transform:rotate(-45deg);width:50%}.toggle.toggle-close :nth-child(2){opacity:0}.toggle.toggle-close :first-child{top:6px;transform:rotate(45deg)}.toggle.toggle-close :last-child{top:-6px;transform:rotate(-45deg)}code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.highlight:hover .copy-btn,pre:hover .copy-btn{opacity:1}figure.highlight .table-container{position:relative;border-radius:0 0 5px 5px}.copy-btn{color:#333;cursor:pointer;line-height:1.6;opacity:0;padding:2px 6px;position:absolute;transition:opacity .2s ease-in-out;color:var(--highlight-foreground);font-size:14px;right:0;top:2px}figure.highlight{border-radius:5px;box-shadow:0 10px 30px 0 rgba(0,0,0,.4);padding-top:30px;overflow:auto;position:relative}figure.highlight::before{background:#fc625d;box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;left:12px;margin-top:-20px;position:absolute;border-radius:50%;content:' ';height:12px;width:12px}code,figure.highlight,kbd,pre{background:var(--highlight-background);color:var(--highlight-foreground)}figure.highlight,pre{line-height:1.6;margin:0 auto 20px}figure.highlight figcaption,pre .caption,pre figcaption{background:var(--highlight-gutter-background);color:var(--highlight-foreground);display:flow-root;font-size:.875em;line-height:1.2;padding:.5em}figure.highlight figcaption a,pre .caption a,pre figcaption a{color:var(--highlight-foreground);float:right}figure.highlight figcaption a:hover,pre .caption a:hover,pre figcaption a:hover{border-bottom-color:var(--highlight-foreground)}code,pre{font-family:consolas,Menlo,monospace,'PingFang SC','Microsoft YaHei'}code{border-radius:3px;font-size:.875em;padding:2px 4px;overflow-wrap:break-word}kbd{border:2px solid #ccc;border-radius:.2em;box-shadow:.1em .1em .2em rgba(0,0,0,.1);font-family:inherit;padding:.1em .3em;white-space:nowrap}figure.highlight pre{border:0;margin:0;padding:10px 0}figure.highlight table{border:0;margin:0;width:auto}figure.highlight td{border:0;padding:0}figure.highlight .gutter{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}figure.highlight .gutter pre{background:var(--highlight-gutter-background);color:var(--highlight-gutter-foreground);padding-left:10px;padding-right:10px;text-align:right}figure.highlight .code pre{padding-left:10px;width:100%}figure.highlight .marked{background:rgba(0,0,0,.3)}pre .caption,pre figcaption{margin-bottom:10px}.gist table{width:auto}.gist table td{border:0}pre code{background:0 0;padding:0;text-shadow:none}.blockquote-center{border-left:0;margin:40px 0;padding:0;position:relative;text-align:center}.blockquote-center::after,.blockquote-center::before{left:0;line-height:1;opacity:.6;position:absolute;width:100%}.blockquote-center::before{border-top:1px solid #ccc;text-align:left;top:-20px;content:'\f10d';font-family:'Font Awesome 6 Free';font-weight:900}.blockquote-center::after{border-bottom:1px solid #ccc;bottom:-20px;text-align:right;content:'\f10e';font-family:'Font Awesome 6 Free';font-weight:900}.blockquote-center div,.blockquote-center p{text-align:center}.group-picture{margin-bottom:20px}.group-picture .group-picture-row{display:flex;gap:3px;margin-bottom:3px}.group-picture .group-picture-column{flex:1}.group-picture .group-picture-column img{height:100%;margin:0;object-fit:cover;width:100%}.post-body .label{color:#555;padding:0 2px}.post-body .label.default{background:#f0f0f0}.post-body .label.primary{background:#efe6f7}.post-body .label.info{background:#e5f2f8}.post-body .label.success{background:#e7f4e9}.post-body .label.warning{background:#fcf6e1}.post-body .label.danger{background:#fae8eb}.post-body .link-grid{display:grid;grid-gap:1.5rem;gap:1.5rem;grid-template-columns:1fr 1fr;margin-bottom:20px;padding:1rem}.post-body .link-grid .link-grid-container{border:solid #ddd;box-shadow:1rem 1rem .5rem rgba(0,0,0,.5);min-height:5rem;min-width:0;padding:.5rem;position:relative;transition:background .3s}.post-body .link-grid .link-grid-container:hover{animation:.5s next-shake;background:var(--card-bg-color)}.post-body .link-grid .link-grid-container:active{box-shadow:.5rem .5rem .25rem rgba(0,0,0,.5);transform:translate(.2rem,.2rem)}.post-body .link-grid .link-grid-container .link-grid-image{border:1px solid #ddd;border-radius:50%;box-sizing:border-box;height:5rem;padding:3px;position:absolute;width:5rem}.post-body .link-grid .link-grid-container p{margin:0 1rem 0 6rem}.post-body .link-grid .link-grid-container p:first-of-type{font-size:1.2em}.post-body .link-grid .link-grid-container p:last-of-type{font-size:.8em;line-height:1.3rem;opacity:.7}.post-body .link-grid .link-grid-container a{border:0;height:100%;left:0;position:absolute;top:0;width:100%}@keyframes next-shake{0%{transform:translate(1pt,1pt) rotate(0)}10%{transform:translate(-1pt,-2pt) rotate(-1deg)}20%{transform:translate(-3pt,0) rotate(1deg)}30%{transform:translate(3pt,2pt) rotate(0)}40%{transform:translate(1pt,-1pt) rotate(1deg)}50%{transform:translate(-1pt,2pt) rotate(-1deg)}60%{transform:translate(-3pt,1pt) rotate(0)}70%{transform:translate(3pt,1pt) rotate(-1deg)}80%{transform:translate(-1pt,-1pt) rotate(1deg)}90%{transform:translate(1pt,2pt) rotate(0)}100%{transform:translate(1pt,-2pt) rotate(-1deg)}}.post-body .note{border-radius:3px;margin-bottom:20px;padding:1em;position:relative;border:1px solid #eee;border-left-width:5px}.post-body .note summary{cursor:pointer;outline:0}.post-body .note summary p{display:inline}.post-body .note h2,.post-body .note h3,.post-body .note h4,.post-body .note h5,.post-body .note h6{border-bottom:initial;margin:0;padding-top:0}.post-body .note :first-child{margin-top:0}.post-body .note :last-child{margin-bottom:0}.post-body .note.default{border-left-color:#777}.post-body .note.default h2,.post-body .note.default h3,.post-body .note.default h4,.post-body .note.default h5,.post-body .note.default h6{color:#777}.post-body .note.primary{border-left-color:#6f42c1}.post-body .note.primary h2,.post-body .note.primary h3,.post-body .note.primary h4,.post-body .note.primary h5,.post-body .note.primary h6{color:#6f42c1}.post-body .note.info{border-left-color:#428bca}.post-body .note.info h2,.post-body .note.info h3,.post-body .note.info h4,.post-body .note.info h5,.post-body .note.info h6{color:#428bca}.post-body .note.success{border-left-color:#5cb85c}.post-body .note.success h2,.post-body .note.success h3,.post-body .note.success h4,.post-body .note.success h5,.post-body .note.success h6{color:#5cb85c}.post-body .note.warning{border-left-color:#f0ad4e}.post-body .note.warning h2,.post-body .note.warning h3,.post-body .note.warning h4,.post-body .note.warning h5,.post-body .note.warning h6{color:#f0ad4e}.post-body .note.danger{border-left-color:#d9534f}.post-body .note.danger h2,.post-body .note.danger h3,.post-body .note.danger h4,.post-body .note.danger h5,.post-body .note.danger h6{color:#d9534f}.post-body .tabs{margin-bottom:20px}.post-body .tabs,.tabs-comment{padding-top:10px}.post-body .tabs ul.nav-tabs,.tabs-comment ul.nav-tabs{background:var(--content-bg-color);display:flex;display:flex;flex-wrap:wrap;justify-content:center;margin:0;padding:0;position:-webkit-sticky;position:sticky;top:0;z-index:5}.post-body .tabs ul.nav-tabs li.tab,.tabs-comment ul.nav-tabs li.tab{border-bottom:1px solid #ddd;border-left:1px solid transparent;border-right:1px solid transparent;border-radius:0;border-top:3px solid transparent;flex-grow:1;list-style-type:none}@media (max-width:413px){.post-body .tabs ul.nav-tabs,.tabs-comment ul.nav-tabs{display:block;margin-bottom:5px}.post-body .tabs ul.nav-tabs li.tab,.tabs-comment ul.nav-tabs li.tab{border-bottom:1px solid transparent;border-left:3px solid transparent;border-right:1px solid transparent;border-top:1px solid transparent;border-radius:0}}.post-body .tabs ul.nav-tabs li.tab a,.tabs-comment ul.nav-tabs li.tab a{border-bottom:initial;display:block;line-height:1.8;padding:.25em .75em;text-align:center;transition:.2s ease-out}.post-body .tabs ul.nav-tabs li.tab a i,.tabs-comment ul.nav-tabs li.tab a i{width:1.285714285714286em}.post-body .tabs ul.nav-tabs li.tab.active,.tabs-comment ul.nav-tabs li.tab.active{border-color:#fc6423 #ddd transparent}@media (max-width:413px){.post-body .tabs ul.nav-tabs li.tab.active,.tabs-comment ul.nav-tabs li.tab.active{border-color:#ddd #ddd #ddd #fc6423}}.post-body .tabs ul.nav-tabs li.tab.active a,.tabs-comment ul.nav-tabs li.tab.active a{cursor:default}.post-body .tabs .tab-content,.tabs-comment .tab-content{border:1px solid #ddd;border-radius:0;border-top-color:transparent}@media (max-width:413px){.post-body .tabs .tab-content,.tabs-comment .tab-content{border-radius:0;border-top-color:#ddd}}.post-body .tabs .tab-content .tab-pane,.tabs-comment .tab-content .tab-pane{padding:20px 20px 0}.post-body .tabs .tab-content .tab-pane:not(.active),.tabs-comment .tab-content .tab-pane:not(.active){display:none}.pagination .next,.pagination .page-number,.pagination .prev,.pagination .space{display:inline-block;margin:-1px 10px 0;padding:0 10px}.algolia-pagination .current .page-number,.pagination .page-number.current{background:#ccc;border-color:#ccc;color:var(--content-bg-color)}.pagination{border-top:1px solid #eee;margin:120px 0 0;text-align:center}.pagination .next,.pagination .page-number,.pagination .prev{border-bottom:0;border-top:1px solid #eee;transition:border-color .2s ease-in-out}.pagination .next:hover,.pagination .page-number:hover,.pagination .prev:hover{border-top-color:var(--link-hover-color)}@media (max-width:767px){.post-body .link-grid{grid-template-columns:1fr}.pagination .next,.pagination .page-number,.pagination .prev,.pagination .space{margin:0 5px}.pagination{border-top:0}.pagination .next,.pagination .page-number,.pagination .prev{border-bottom:1px solid #eee;border-top:0}.pagination .next:hover,.pagination .page-number:hover,.pagination .prev:hover{border-bottom-color:var(--link-hover-color)}.site-meta{text-align:center}}.pagination .space{margin:0;padding:0}.comments{margin-top:60px;overflow:hidden}.comment-button-group{display:flex;display:flex;flex-wrap:wrap;justify-content:center;justify-content:center;margin:1em 0}.comment-button-group .comment-button{margin:.1em .2em}.comment-button-group .comment-button.active{background:var(--btn-default-hover-bg);border-color:var(--btn-default-hover-border-color);color:var(--btn-default-hover-color)}.comment-position{display:none}.comment-position.active{display:block}.tabs-comment{margin-top:4em;padding-top:0}.tabs-comment .comments{margin-top:0;padding-top:0}.headband{background:var(--theme-color);height:3px}@media (max-width:991px){.headband{display:none}}.site-brand-container{display:flex;flex-shrink:0;padding:0 10px}.use-motion .column,.use-motion .site-brand-container .toggle{opacity:0}.site-meta{flex-grow:1;text-align:center}.custom-logo-image{margin-top:20px}@media (max-width:991px){.custom-logo-image{display:none}}.brand{border-bottom:0;color:var(--brand-color);display:inline-block;padding:0}.brand:hover{color:var(--brand-hover-color)}.site-title{font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-size:1.375em;font-weight:400;line-height:1.5;margin:0}.site-subtitle{color:#ddd;font-size:.8125em;margin:10px 10px 0}.use-motion .custom-logo-image,.use-motion .site-subtitle,.use-motion .site-title{opacity:0;position:relative;top:-10px}.site-nav-right,.site-nav-toggle{display:none}.site-nav-right .toggle,.site-nav-toggle .toggle{color:var(--text-color);padding:10px;width:22px}.site-nav-right .toggle .toggle-line,.site-nav-toggle .toggle .toggle-line{background:var(--text-color);border-radius:1px}@media (max-width:767px){.site-nav-right,.site-nav-toggle{display:flex;flex-direction:column;justify-content:center}.site-nav{--scroll-height:0;height:0;overflow:hidden;transition:height .2s ease-in-out}body:not(.site-nav-on) .site-nav .animated{animation:none}body.site-nav-on .site-nav{height:var(--scroll-height)}}.menu{margin:0;padding:1em 0;text-align:center}.menu-item{display:inline-block;list-style:none;margin:0 10px}@media (max-width:767px){.menu-item{display:block;margin-top:10px}.menu-item.menu-item-search{display:none}}.menu-item a{border-bottom:0;display:block;font-size:.8125em;transition:border-color .2s ease-in-out}.menu-item a.menu-item-active,.menu-item a:hover{background:var(--menu-item-bg-color)}.menu-item .fa,.menu-item .fab,.menu-item .far,.menu-item .fas{margin-right:8px}.menu-item .badge{display:inline-block;font-weight:700;line-height:1;margin-left:.35em;margin-top:.35em;text-align:center;white-space:nowrap}.use-motion .menu-item{visibility:hidden}.github-corner :hover .octo-arm{animation:560ms ease-in-out octocat-wave}.github-corner svg{color:#fff;fill:var(--theme-color);position:absolute;right:0;top:0;z-index:5}@media (max-width:991px){.github-corner{display:none}.github-corner svg{color:var(--theme-color);fill:#fff}.github-corner .github-corner:hover .octo-arm{animation:none}.github-corner .github-corner .octo-arm{animation:560ms ease-in-out octocat-wave}}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}.sidebar-inner{color:#999;padding:18px 10px;text-align:center;display:flex;flex-direction:column;justify-content:center}.cc-license .cc-opacity{border-bottom:0;opacity:.7}.cc-license .cc-opacity:hover{opacity:.9}.cc-license img{display:inline-block}.site-author-image{border:1px solid #eee;max-width:120px;padding:2px}.site-author-name{color:var(--text-color);font-weight:600;margin:0}.site-description{color:#999;font-size:.8125em;margin-top:0}.links-of-author a{font-size:.8125em}.links-of-author .fa,.links-of-author .fab,.links-of-author .far,.links-of-author .fas{margin-right:2px}.sidebar .sidebar-button:not(:first-child){margin-top:15px}.sidebar .sidebar-button button{background:0 0;cursor:pointer;line-height:2;padding:0 15px;border-radius:4px}.sidebar .sidebar-button button .fa,.sidebar .sidebar-button button .fab,.sidebar .sidebar-button button .far,.sidebar .sidebar-button button .fas{margin-right:5px}.links-of-blogroll{font-size:.8125em}.links-of-blogroll-title{font-size:.875em;font-weight:600}.links-of-blogroll-list{list-style:none;margin:0;padding:0}.sidebar-nav{display:none;margin:0;padding-bottom:20px;padding-left:0}.sidebar-nav-active .sidebar-nav{display:block}.sidebar-nav li{border-bottom:1px solid transparent;color:var(--text-color);cursor:pointer;display:inline-block;font-size:.875em}.sidebar-nav li.sidebar-nav-overview{margin-left:10px}.sidebar-nav li:hover{color:#fc6423}.sidebar-overview-active .sidebar-nav-overview,.sidebar-toc-active .sidebar-nav-toc{border-bottom-color:#fc6423;color:#fc6423}.sidebar-overview-active .sidebar-nav-overview:hover,.sidebar-toc-active .sidebar-nav-toc:hover{color:#fc6423}.sidebar-panel-container{flex:1;overflow-x:hidden;overflow-y:auto}.sidebar-panel{display:none}.sidebar-overview-active .site-overview-wrap{display:flex;flex-direction:column;justify-content:center;gap:10px}.sidebar-toc-active .post-toc-wrap{display:block}.sidebar-toggle{bottom:61px;height:16px;padding:5px;width:16px;background:#222;cursor:pointer;opacity:.6;position:fixed;z-index:30;right:30px}.sidebar-toggle:hover{opacity:.8}@media (max-width:991px){.sidebar-toggle{right:20px;opacity:.8}}.sidebar-toggle:hover .toggle-line{background:#fc6423}@media (any-hover:hover){body:not(.sidebar-active) .sidebar-toggle:hover :first-child{left:50%;top:2px;transform:rotate(45deg);width:50%}body:not(.sidebar-active) .sidebar-toggle:hover :last-child{left:50%;top:-2px;transform:rotate(-45deg);width:50%}}.sidebar-active .sidebar-toggle :nth-child(2){opacity:0}.sidebar-active .sidebar-toggle :first-child{top:6px;transform:rotate(45deg)}.sidebar-active .sidebar-toggle :last-child{top:-6px;transform:rotate(-45deg)}.post-toc{font-size:.875em}.post-toc ol{list-style:none;margin:0;padding:0 2px 5px 10px;text-align:left}.post-toc ol>ol{padding-left:0}.post-toc ol a{transition:.2s ease-in-out}.post-toc .nav-item{line-height:1.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.post-toc .nav .nav-child{display:none}.post-toc .nav .active-current>.nav-child,.post-toc .nav .active-current>.nav-child>.nav-item,.post-toc .nav .active>.nav-child{display:block}.post-toc .nav .active>a{border-bottom-color:#fc6423;color:#fc6423}.post-toc .nav .active-current>a,.post-toc .nav .active-current>a:hover{color:#fc6423}.site-state{display:flex;flex-wrap:wrap;justify-content:center;line-height:1.4}.site-state-item a{border-bottom:0;display:block}.site-state-item-count{display:block;font-size:1em;font-weight:600}.site-state-item-name{color:#999;font-size:.8125em}.sidebar-post-related{font-size:.8125em;padding:18px 0 0}.popular-posts{margin:0;padding:1em 0;text-align:left}.popular-posts .popular-posts-item{display:block}.popular-posts .popular-posts-item .popular-posts-link{border-bottom:0;display:block;padding:5px 20px;transition:background .2s ease-in-out}.popular-posts .popular-posts-item .popular-posts-link:hover{background:var(--menu-item-bg-color)}.popular-posts .popular-posts-item .popular-posts-time{color:#999}.footer{color:#999;font-size:.875em;padding:20px 0}.footer.footer-fixed{bottom:0;left:0;position:absolute;right:0}.footer-inner{box-sizing:border-box;text-align:center;display:flex;flex-direction:column;justify-content:center;margin:0 auto;width:calc(100% - 20px)}@media (max-width:767px){.menu-item .badge{float:right;margin-left:0}.footer-inner{width:auto}}@media (min-width:1200px){.footer-inner{width:1160px}}@media (min-width:1600px){.footer-inner{width:73%}}.use-motion .footer{opacity:0}.languages{display:inline-block;font-size:1.125em;position:relative}.languages .lang-select-label span{margin:0 .5em}.languages .lang-select{height:100%;left:0;opacity:0;position:absolute;top:0;width:100%}.with-love{color:red;display:inline-block;margin:0 5px}.beian img{display:inline-block;margin:0 3px;vertical-align:middle}.busuanzi-count #busuanzi_container_site_pv,.busuanzi-count #busuanzi_container_site_uv{display:none}@keyframes icon-animate{0%,100%{transform:scale(1)}10%,30%{transform:scale(.9)}20%,40%,50%,60%,70%,80%{transform:scale(1.1)}}@media (max-width:567px){.main-inner{padding:initial!important}.posts-expand .post-header{margin-bottom:10px!important}.post-block{margin-top:initial!important;padding:8px 18px!important}.post-body h1,.post-body h2,.post-body h3,.post-body h4,.post-body h5,.post-body h6{margin:20px 0 8px}.post-body .note h1,.post-body .note h2,.post-body .note h3,.post-body .note h4,.post-body .note h5,.post-body .note h6,.post-body .tabs .tab-content .tab-pane h1,.post-body .tabs .tab-content .tab-pane h2,.post-body .tabs .tab-content .tab-pane h3,.post-body .tabs .tab-content .tab-pane h4,.post-body .tabs .tab-content .tab-pane h5,.post-body .tabs .tab-content .tab-pane h6{margin:0 5px}.post-body>p{margin:0 0 10px}.post-body .note>p,.post-body .tabs .tab-content .tab-pane>p{padding:0 5px}.post-body img,.post-body video{margin-bottom:10px!important}.post-body .note{margin-bottom:10px!important;padding:10px!important}.post-body .tabs .tab-content .tab-pane{padding:10px 10px 0!important}.post-eof{margin:40px auto 20px!important}.pagination{margin-top:40px}}.back-to-top{font-size:12px;align-items:center;bottom:-100px;color:#fff;display:flex;height:26px;transition:bottom .2s ease-in-out;background:#222;cursor:pointer;opacity:.6;position:fixed;z-index:30;right:30px}.back-to-top span{margin-right:8px;display:none}.back-to-top .fa{text-align:center;width:26px}.back-to-top:hover{opacity:.8;color:#fc6423}.back-to-top.back-to-top-on{bottom:30px}.rtl.post-body a,.rtl.post-body h1,.rtl.post-body h2,.rtl.post-body h3,.rtl.post-body h4,.rtl.post-body h5,.rtl.post-body h6,.rtl.post-body li,.rtl.post-body ol,.rtl.post-body p,.rtl.post-body ul{direction:rtl;font-family:UKIJ Ekran}.rtl.post-title{font-family:UKIJ Ekran}.post-button{margin-top:40px;text-align:center}.use-motion .collection-header,.use-motion .comments,.use-motion .pagination,.use-motion .post-block,.use-motion .post-body,.use-motion .post-header{visibility:hidden}.posts-collapse .post-content{margin-bottom:35px;margin-left:35px;position:relative}@media (max-width:767px){.posts-collapse .post-content{margin-left:0;margin-right:0}}.posts-collapse .post-content .collection-title{font-size:1.125em;position:relative}.posts-collapse .post-content .collection-title::before{background:#999;border:1px solid #fff;margin-left:-6px;margin-top:-4px;position:absolute;top:50%;border-radius:50%;content:' ';height:10px;width:10px}.posts-collapse .post-content .collection-year{font-size:1.5em;font-weight:700;margin:60px 0;position:relative}.posts-collapse .post-content .collection-year::before{background:#bbb;margin-left:-4px;margin-top:-4px;position:absolute;top:50%;border-radius:50%;content:' ';height:8px;width:8px}.posts-collapse .post-content .collection-header{display:block;margin-left:20px}.posts-collapse .post-content .collection-header small{color:#bbb;margin-left:5px}.posts-collapse .post-content .post-header{border-bottom:1px dashed #ccc;margin:30px 2px 0;padding-left:15px;position:relative;transition:border .2s ease-in-out}.posts-collapse .post-content .post-header::before{background:#bbb;border:1px solid #fff;left:-6px;position:absolute;top:.75em;transition:background .2s ease-in-out;border-radius:50%;content:' ';height:6px;width:6px}.posts-collapse .post-content .post-header:hover{border-bottom-color:#666}.posts-collapse .post-content .post-header:hover::before{background:#222}.posts-collapse .post-content .post-meta-container{display:inline;font-size:.75em;margin-right:10px}.posts-collapse .post-content .post-title{display:inline}.posts-collapse .post-content .post-title a{border-bottom:0;color:var(--link-color)}.posts-collapse .post-content .post-title .fa-external-link-alt{font-size:.875em;margin-left:5px}.posts-collapse .post-content::before{background:#f5f5f5;content:' ';height:100%;margin-left:-2px;position:absolute;top:1.25em;width:4px}.post-body{font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;overflow-wrap:break-word}@media (min-width:1200px){.post-body{font-size:1.125em}}@media (min-width:992px){.post-body{text-align:justify}}.post-body h1 .header-anchor,.post-body h1 .headerlink,.post-body h2 .header-anchor,.post-body h2 .headerlink,.post-body h3 .header-anchor,.post-body h3 .headerlink,.post-body h4 .header-anchor,.post-body h4 .headerlink,.post-body h5 .header-anchor,.post-body h5 .headerlink,.post-body h6 .header-anchor,.post-body h6 .headerlink{border-bottom-style:none;color:inherit;float:right;font-size:.875em;margin-left:10px;opacity:0}.post-body h1 .header-anchor::before,.post-body h1 .headerlink::before,.post-body h2 .header-anchor::before,.post-body h2 .headerlink::before,.post-body h3 .header-anchor::before,.post-body h3 .headerlink::before,.post-body h4 .header-anchor::before,.post-body h4 .headerlink::before,.post-body h5 .header-anchor::before,.post-body h5 .headerlink::before,.post-body h6 .header-anchor::before,.post-body h6 .headerlink::before{content:'\f0c1';font-family:'Font Awesome 6 Free';font-weight:900}.post-body h1:hover .header-anchor,.post-body h1:hover .headerlink,.post-body h2:hover .header-anchor,.post-body h2:hover .headerlink,.post-body h3:hover .header-anchor,.post-body h3:hover .headerlink,.post-body h4:hover .header-anchor,.post-body h4:hover .headerlink,.post-body h5:hover .header-anchor,.post-body h5:hover .headerlink,.post-body h6:hover .header-anchor,.post-body h6:hover .headerlink{opacity:.5}.post-body h1:hover .header-anchor:hover,.post-body h1:hover .headerlink:hover,.post-body h2:hover .header-anchor:hover,.post-body h2:hover .headerlink:hover,.post-body h3:hover .header-anchor:hover,.post-body h3:hover .headerlink:hover,.post-body h4:hover .header-anchor:hover,.post-body h4:hover .headerlink:hover,.post-body h5:hover .header-anchor:hover,.post-body h5:hover .headerlink:hover,.post-body h6:hover .header-anchor:hover,.post-body h6:hover .headerlink:hover{opacity:1}.post-body .exturl .fa{font-size:.875em;margin-left:4px}.post-body .fancybox+figcaption,.post-body .image-caption,.post-body img+figcaption{color:#999;font-size:.875em;font-weight:700;line-height:1;margin:-15px auto 15px;text-align:center}.post-body embed,.post-body iframe,.post-body img,.post-body video{margin-bottom:20px}.post-body .video-container{height:0;margin-bottom:20px;overflow:hidden;padding-top:75%;position:relative;width:100%}.post-body .video-container embed,.post-body .video-container iframe,.post-body .video-container object{height:100%;left:0;margin:0;position:absolute;top:0;width:100%}.post-gallery{display:flex;min-height:200px}.post-gallery .post-gallery-image{flex:1}.post-gallery .post-gallery-image:not(:first-child){clip-path:polygon(40px 0,100% 0,100% 100%,0 100%);margin-left:-20px}.post-gallery .post-gallery-image:not(:last-child){margin-right:-20px}.post-gallery .post-gallery-image img{height:100%;object-fit:cover;opacity:1;width:100%}.posts-expand .post-gallery{margin-bottom:60px}.posts-collapse .post-gallery{margin:15px 0}.posts-expand .post-header{font-size:1.125em;margin-bottom:60px;text-align:center}.posts-expand .post-title{font-size:1.5em;font-weight:400;margin:initial;overflow-wrap:break-word}.posts-expand .post-title-link{border-bottom:0;color:var(--link-color);display:inline-block;position:relative}.posts-expand .post-title-link::before{background:var(--link-color);bottom:0;content:'';height:2px;left:0;position:absolute;transform:scaleX(0);transition:transform .2s ease-in-out;width:100%}.posts-expand .post-title-link:hover::before{transform:scaleX(1)}.posts-expand .post-title-link .fa-external-link-alt{font-size:.875em;margin-left:5px}.post-sticky-flag{display:inline-block;margin-right:8px;transform:rotate(30deg)}.posts-expand .post-meta-container{color:#999;font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-size:.75em;margin-top:3px}.posts-expand .post-meta-container .post-description{font-size:.875em;margin-top:2px}.posts-expand .post-meta-container time{border-bottom:1px dashed #999}.post-meta{display:flex;flex-wrap:wrap;justify-content:center}:not(.post-meta-break)+.post-meta-item::before{content:'|';margin:0 .5em}.post-meta-item-icon{margin-right:3px}@media (max-width:991px){.back-to-top{right:20px;opacity:.8}.post-body{text-align:justify}.post-meta-item-text{display:none}}.post-meta-break{flex-basis:100%;height:0}#busuanzi_container_page_pv{display:none}.post-nav{border-top:1px solid #eee;display:flex;gap:30px;justify-content:space-between;margin-top:1em;padding:10px 5px 0}.post-nav-item{flex:1}.post-nav-item a{border-bottom:0;display:block;font-size:.875em;line-height:1.6}.post-nav-item a:active{top:2px}.post-nav-item .fa{font-size:.75em}.post-nav-item:first-child .fa{margin-right:5px}.post-nav-item:last-child{text-align:right}.post-nav-item:last-child .fa{margin-left:5px}.post-footer{display:flex;flex-direction:column;justify-content:center}.post-eof{background:#ccc;height:1px;margin:80px auto 60px;width:8%}.post-block:last-of-type .post-eof{display:none}.post-copyright ul{list-style:none;overflow:hidden;padding:.5em 1em;position:relative;background:var(--card-bg-color);border-left:3px solid #ff2a2a;margin:1em 0 0}.post-copyright ul::after{content:'\f25e';font-family:'Font Awesome 6 Brands';font-size:200px;opacity:.1;position:absolute;right:-50px;top:-150px}.post-tags{margin-top:40px;text-align:center}.post-tags a{display:inline-block;font-size:.8125em}.post-tags a:not(:last-child){margin-right:10px}.social-like{border-top:1px solid #eee;font-size:.875em;margin-top:1em;padding-top:1em;text-align:center}.reward-container{margin:1em 0 0;padding:1em 0;text-align:center}.reward-container button{background:0 0;color:#fc6423;cursor:pointer;line-height:2;padding:0 15px;border:2px solid #fc6423;border-radius:2px;outline:0;transition:.2s ease-in-out;vertical-align:text-top}.reward-container button:hover{background:#fc6423;color:#fff}.post-reward{display:none;padding-top:20px}.post-reward.active{display:block}.post-reward div{display:inline-block}.post-reward div span{display:block}.post-reward img{display:inline-block;margin:.8em 2em 0;max-width:100%;width:180px}@keyframes next-roll{from{transform:rotateZ(30deg)}to{transform:rotateZ(-30deg)}}.category-all-page .category-all-title{text-align:center}.category-all-page .category-all{margin-top:20px}.category-all-page .category-list{list-style:none;margin:0;padding:0}.category-all-page .category-list-item{margin:5px 10px}.category-all-page .category-list-count{color:#bbb}.category-all-page .category-list-count::before{content:' ('}.category-all-page .category-list-count::after{content:') '}.category-all-page .category-list-child{padding-left:10px}.event-list hr{background:#222;margin:20px 0 45px}.event-list hr::after{background:#222;color:#fff;content:'NOW';display:inline-block;font-weight:700;padding:0 5px}.event-list .event{--event-background:#222;--event-foreground:#bbb;--event-title:#fff;background:var(--event-background);padding:15px}.event-list .event .event-summary{border-bottom:0;color:var(--event-title);margin:0;padding:0 0 0 35px;position:relative}.event-list .event .event-summary::before{animation:1s ease-in-out infinite alternate dot-flash;background:var(--event-title);left:0;margin-top:-6px;position:absolute;top:50%;border-radius:50%;content:' ';height:12px;width:12px}.event-list .event:nth-of-type(odd) .event-summary::before{animation-delay:.5s}.event-list .event:not(:last-child){margin-bottom:20px}.event-list .event .event-relative-time{color:var(--event-foreground);display:inline-block;font-size:12px;font-weight:400;padding-left:12px}.event-list .event .event-details{color:var(--event-foreground);display:block;line-height:18px;padding:6px 0 6px 35px}.event-list .event .event-details::before{color:var(--event-foreground);display:inline-block;margin-right:9px;width:14px;font-family:'Font Awesome 6 Free';font-weight:900}.event-list .event .event-details.event-location::before{content:'\f041'}.event-list .event .event-details.event-duration::before{content:'\f017'}.event-list .event .event-details.event-description::before{content:'\f024'}.event-list .event-past{--event-background:#f5f5f5;--event-foreground:#999;--event-title:#222}@keyframes dot-flash{from{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.8)}}ul.breadcrumb{font-size:.75em;list-style:none;margin:1em 0;padding:0 2em;text-align:center}ul.breadcrumb li{display:inline}ul.breadcrumb li:not(:first-child)::before{content:'/\00a0';font-weight:400;padding:.5em}ul.breadcrumb li:last-child{font-weight:700}.tag-cloud{text-align:center}.tag-cloud a{display:inline-block;margin:10px}.tag-cloud-0{border-bottom-color:#aaa;color:#aaa}.tag-cloud-1{border-bottom-color:#9a9a9a;color:#9a9a9a}.tag-cloud-2{border-bottom-color:#8b8b8b;color:#8b8b8b}.tag-cloud-3{border-bottom-color:#7c7c7c;color:#7c7c7c}.tag-cloud-4{border-bottom-color:#6c6c6c;color:#6c6c6c}.tag-cloud-5{border-bottom-color:#5d5d5d;color:#5d5d5d}.tag-cloud-6{border-bottom-color:#4e4e4e;color:#4e4e4e}.tag-cloud-7{border-bottom-color:#3e3e3e;color:#3e3e3e}.tag-cloud-8{border-bottom-color:#2f2f2f;color:#2f2f2f}.tag-cloud-9{border-bottom-color:#202020;color:#202020}.tag-cloud-10{border-bottom-color:#111;color:#111}.search-active{overflow:hidden}.search-pop-overlay{background:rgba(0,0,0,0);display:flex;height:100%;left:0;position:fixed;top:0;transition:visibility .4s,background .4s;visibility:hidden;width:100%;z-index:40}.search-active .search-pop-overlay{background:rgba(0,0,0,.3);visibility:visible}.search-popup{background:var(--card-bg-color);border-radius:5px;height:80%;margin:auto;transform:scale(0);transition:transform .4s;width:700px}.search-active .search-popup{transform:scale(1)}@media (max-width:767px){.search-popup{border-radius:0;height:100%;width:100%}}.search-popup .popup-btn-close,.search-popup .search-icon{color:#999;font-size:18px;padding:0 10px}.search-popup .popup-btn-close{cursor:pointer}.search-popup .popup-btn-close:hover .fa{color:#222}.search-popup .search-header{background:#eee;border-top-left-radius:5px;border-top-right-radius:5px;display:flex;padding:5px}.search-popup input.search-input{background:0 0;border:0;outline:0;width:100%}.search-popup input.search-input::-webkit-search-cancel-button{display:none}.search-popup .search-result-container{height:calc(100% - 55px);overflow:auto;padding:5px 25px}.search-popup .search-result-container hr{margin:5px 0 10px}.search-popup .search-result-container hr:first-child{display:none}.search-popup .search-result-list{margin:0 5px;padding:0}.search-popup a.search-result-title{font-weight:700}.search-popup p.search-result{border-bottom:1px dashed #ccc;padding:5px 0}.search-input-container{flex-grow:1}.search-input-container form{padding:2px}.search-stats{align-items:center;display:flex;justify-content:space-between}.search-stats img{height:1em;margin:0}.algolia-pagination{margin:40px 0;opacity:1;padding:0}.algolia-pagination .pagination-item{display:inline-block}.algolia-pagination .current .page-number{cursor:default}.algolia-pagination .disabled-item{visibility:hidden}.use-motion .animated{animation-fill-mode:none;visibility:inherit}.use-motion .sidebar .animated{animation-fill-mode:both}.header{background:var(--content-bg-color);border-radius:initial;box-shadow:initial}.main{align-items:stretch;display:flex;justify-content:space-between;margin:0 auto;width:calc(100% - 20px)}@media (max-width:767px){.main{width:auto}}@media (min-width:1200px){.main{width:1160px}}@media (min-width:1600px){.main{width:73%}}@media (max-width:991px){.header{border-radius:initial}.main{display:block;width:auto}}.main-inner{border-radius:initial;box-sizing:border-box;width:calc(100% - 252px)}.footer-inner{padding-left:252px}@media (max-width:991px){.main-inner{border-radius:initial;width:100%}.footer-inner{padding-left:0;padding-right:0;width:auto}}.column{width:240px}.site-brand-container{background:var(--theme-color)}.site-meta{padding:20px 0}.site-nav-right .toggle,.site-nav-toggle .toggle{color:#fff}.site-nav-right .toggle .toggle-line,.site-nav-toggle .toggle .toggle-line{background:#fff}@media (min-width:768px) and (max-width:991px){.site-nav-right,.site-nav-toggle{display:flex;flex-direction:column;justify-content:center}.site-nav{--scroll-height:0;height:0;overflow:hidden;transition:height .2s ease-in-out}body:not(.site-nav-on) .site-nav .animated{animation:none}body.site-nav-on .site-nav{height:var(--scroll-height)}}.menu .menu-item{display:block;margin:0}.menu .menu-item a{padding:5px 20px;position:relative;text-align:left;transition-property:background-color}.menu .menu-item .badge{background:#ccc;border-radius:10px;color:var(--content-bg-color);float:right;padding:2px 5px;text-shadow:1px 1px 0 rgba(0,0,0,.1)}.main-menu .menu-item-active::after{background:#bbb;border-radius:50%;content:' ';height:6px;margin-top:-3px;position:absolute;right:15px;top:50%;width:6px}.sub-menu{margin:0;padding:6px 0}.sub-menu .menu-item{display:inline-block}.sub-menu .menu-item a{background:0 0;margin:5px 10px;padding:initial}.sub-menu .menu-item a:hover{background:0 0;color:#fc6423}.sub-menu .menu-item-active{border-bottom-color:#fc6423;color:#fc6423}.sub-menu .menu-item-active:hover{border-bottom-color:#fc6423}.sidebar{position:-webkit-sticky;position:sticky;top:12px}@media (max-width:991px){.column{width:auto}.site-nav-on .site-brand-container{box-shadow:0 0 16px rgba(0,0,0,.5)}.menu .menu-item.menu-item-search,.sidebar{display:none}}.sidebar-inner{background:var(--content-bg-color);border-radius:initial;box-shadow:initial;box-sizing:border-box;color:var(--text-color);margin-top:12px;max-height:calc(100vh - 24px);visibility:hidden}.site-state-item{padding:0 10px}.sidebar .sidebar-button{border-bottom:1px dotted #ccc;border-top:1px dotted #ccc}.sidebar .sidebar-button button{border:0;color:#fc6423;display:block;width:100%}.sidebar .sidebar-button button:hover{background:0 0;border:0;color:#e34603}.links-of-author{display:flex;flex-wrap:wrap;justify-content:center}.links-of-author-item{margin:5px 0 0;width:50%}.links-of-author-item a{box-sizing:border-box;max-width:100%;overflow:hidden;padding:0 5px;text-overflow:ellipsis;white-space:nowrap;border-bottom:0;border-radius:4px;display:block}.links-of-author-item a:hover{background:var(--body-bg-color)}.main-inner{background:var(--content-bg-color);box-shadow:initial;padding:40px}@media (max-width:991px){.main-inner{padding:20px}}.sub-menu{border-bottom:1px solid #ddd}.post-block:first-of-type{padding-top:40px}@media (max-width:767px){.pagination{margin-bottom:10px}}</style><link as=style href=https://fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext onload=this.rel='stylesheet' rel=preload><link crossorigin=anonymous href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css integrity=sha256-Z1K5uhUaJXA7Ll0XrZ/0JhX4lAtZFpT6jkKrEDT0drU= rel=stylesheet><link crossorigin=anonymous href=https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css integrity=sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE= rel=stylesheet><link crossorigin=anonymous href=https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css integrity=sha256-Vzbj7sDDS/woiFS3uNKo8eIuni59rjyNGtXfstRzStA= rel=stylesheet><script class=next-config data-name=main type=application/json>{"hostname":"nicksxs.me","root":"/","images":"/images","scheme":"Pisces","darkmode":false,"version":"8.14.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果:${query}","hits_time":"找到 ${hits} 个搜索结果(用时 ${time} 毫秒)","hits":"找到 ${hits} 个搜索结果"},"algolia":{"appID":"663Q99OQQD","apiKey":"e461a1371d12cec1491c1153b288a9ed","indexName":"nicksxs","hits":{"per_page":10}}}</script><script src=/js/config.js></script><meta content="learn from zero,技术博客,Nicksxs,史学森" name=description><meta content=website property=og:type><meta content="Nicksxs's Blog" property=og:title><meta content=https://nicksxs.me/page/11/index.html property=og:url><meta content="Nicksxs's Blog" property=og:site_name><meta content="learn from zero,技术博客,Nicksxs,史学森" property=og:description><meta content=zh_CN property=og:locale><meta content=Nicksxs property=article:author><meta content=Nicksxs,史学森,米方方,米方方的男朋友,森哥 property=article:tag><meta content=summary name=twitter:card><link href=https://nicksxs.me/page/11/ rel=canonical><script class=next-config data-name=page type=application/json>{"sidebar":"","isHome":true,"isPost":false,"lang":"zh-CN","comments":"","permalink":"","path":"page/11/index.html","title":""}</script><script class=next-config data-name=calendar type=application/json>""</script><title>Nicksxs's Blog - What hurts more, the pain of hard work or the pain of regret?</title><script async src=https://www.googletagmanager.com/gtag/js?id=UA-61358619-1></script><script class=next-config data-name=google_analytics type=application/json>{"tracking_id":"UA-61358619-1","only_pageview":false}</script><script src=/js/third-party/analytics/google-analytics.js></script><script src=/js/third-party/analytics/baidu-analytics.js></script><script async src=https://hm.baidu.com/hm.js?20f33b3c0c0eff9b1522999c0015646d></script><noscript><link href=/css/noscript.css rel=stylesheet></noscript><link title="Nicksxs's Blog" href=/atom.xml rel=alternate type=application/atom+xml><body class=use-motion itemscope itemtype=http://schema.org/WebPage><div class=headband></div><main class=main><div class=column><header class=header itemscope itemtype=http://schema.org/WPHeader><div class=site-brand-container><div class=site-nav-toggle><div aria-label=切换导航栏 class=toggle role=button><span class=toggle-line></span><span class=toggle-line></span><span class=toggle-line></span></div></div><div class=site-meta><a class=brand href=/ rel=start><i class=logo-line></i><h1 class=site-title>Nicksxs's Blog</h1><i class=logo-line></i></a><p class=site-subtitle itemprop=description>What hurts more, the pain of hard work or the pain of regret?</div><div class=site-nav-right><div class="toggle popup-trigger" aria-label=搜索 role=button><i class="fa fa-search fa-fw fa-lg"></i></div></div></div><nav class=site-nav><ul class="main-menu menu"><li class="menu-item menu-item-home"><a href=/ rel=section><i class="fa fa-home fa-fw"></i>首页</a><li class="menu-item menu-item-about"><a href=/about/ rel=section><i class="fa fa-user fa-fw"></i>关于</a><li class="menu-item menu-item-tags"><a href=/tags/ rel=section><i class="fa fa-tags fa-fw"></i>标签</a><li class="menu-item menu-item-categories"><a href=/categories/ rel=section><i class="fa fa-th fa-fw"></i>分类</a><li class="menu-item menu-item-archives"><a href=/archives/ rel=section><i class="fa fa-archive fa-fw"></i>归档</a><li class="menu-item menu-item-top"><a href=/top/ rel=section><i class="fa fa-th fa-fw"></i>热度</a><li class="menu-item menu-item-sitemap"><a href=/sitemap.xml rel=section><i class="fa fa-sitemap fa-fw"></i>站点地图</a><li class="menu-item menu-item-commonweal"><a href=/404/ rel=section><i class="fa fa-heartbeat fa-fw"></i>公益 404</a><li class="menu-item menu-item-search"><a class=popup-trigger role=button><i class="fa fa-search fa-fw"></i>搜索</a></ul></nav><div class=search-pop-overlay><div class="popup search-popup"><div class=search-header><span class=search-icon><i class="fa fa-search"></i></span><div class=search-input-container></div><span class=popup-btn-close role=button><i class="fa fa-times-circle"></i></span></div><div class=search-result-container><div class=algolia-stats><hr></div><div class=algolia-hits></div><div class=algolia-pagination></div></div></div></div></header><aside class=sidebar><div class="sidebar-inner sidebar-overview-active"><ul class=sidebar-nav><li class=sidebar-nav-toc>文章目录<li class=sidebar-nav-overview>站点概览</ul><div class=sidebar-panel-container><div class="post-toc-wrap sidebar-panel"></div><div class="site-overview-wrap sidebar-panel"><div class="site-author animated" itemprop=author itemscope itemtype=http://schema.org/Person><img alt=Nicksxs class=site-author-image itemprop=image src=/uploads/avatar.jpg><p class=site-author-name itemprop=name>Nicksxs<div class=site-description itemprop=description>learn from zero,技术博客,Nicksxs,史学森</div></div><div class="site-state-wrap animated"><nav class=site-state><div class="site-state-item site-state-posts"><a href=/archives/><span class=site-state-item-count>228</span> <span class=site-state-item-name>日志</span></a></div><div class="site-state-item site-state-categories"><a href=/categories/><span class=site-state-item-count>158</span> <span class=site-state-item-name>分类</span></a></div><div class="site-state-item site-state-tags"><a href=/tags/><span class=site-state-item-count>296</span> <span class=site-state-item-name>标签</span></a></div></nav></div><div class="links-of-author animated"><span class=links-of-author-item><a rel="noopener me" title="GitHub → https://github.com/nicksxs" href=https://github.com/nicksxs target=_blank><i class="fab fa-github fa-fw"></i>GitHub</a> </span><span class=links-of-author-item><a rel="noopener me" title="E-Mail → mailto:nicksxs1202@gmail.com" href=mailto:nicksxs1202@gmail.com target=_blank><i class="fa fa-envelope fa-fw"></i>E-Mail</a></span></div><div class="cc-license animated" itemprop=license><a class=cc-opacity href=https://creativecommons.org/licenses/by-nc-sa/4.0/ rel=noopener target=_blank><img alt="Creative Commons" src=https://cdnjs.cloudflare.com/ajax/libs/creativecommons-vocabulary/2020.11.3/assets/license_badges/small/by_nc_sa.svg></a></div><div class=post-gallery itemscope itemtype=http://schema.org/ImageGallery style=height:120px;min-height:120px><div class=post-gallery-row><a class="post-gallery-img fancybox" href=https://url.cn/LLWrL7gx itemprop=url itemscope itemtype=http://schema.org/ImageObject rel=gallery_ target=_blank><img alt=腾讯云推广 itemprop=contentUrl src=https://img.nicksxs.com/blog/345X200.jpg style=padding:12px></a></div></div><script charset=utf-8 src=/js/tagcloud.js></script><script charset=utf-8 src=/js/tagcanvas.js></script><div class=widget-wrap><div class="widget tagcloud" id=myCanvasContainer><canvas height=250 id=resCanvas width=250><ul class=tag-list itemprop=keywords><li class=tag-list-item><a class=tag-list-link href=/tags/2019/ rel=tag>2019</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/2020/ rel=tag>2020</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/2021/ rel=tag>2021</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/2022/ rel=tag>2022</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/2023/ rel=tag>2023</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/2PC/ rel=tag>2PC</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/360-%E5%85%A8%E5%AE%B6%E6%A1%B6/ rel=tag>360 全家桶</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/3PC/ rel=tag>3PC</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/3Sum-Closest/ rel=tag>3Sum Closest</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/AOP/ rel=tag>AOP</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Adaptive/ rel=tag>Adaptive</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Apollo/ rel=tag>Apollo</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/AutoConfiguration/ rel=tag>AutoConfiguration</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/Binary-Tree/ rel=tag>Binary Tree</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/Broker/ rel=tag>Broker</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/C/ rel=tag>C</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/C/ rel=tag>C++</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/CachedThreadPool/ rel=tag>CachedThreadPool</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Comparator/ rel=tag>Comparator</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/DFS/ rel=tag>DFS</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/DP/ rel=tag>DP</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/DefaultMQPushConsumer/ rel=tag>DefaultMQPushConsumer</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Design-Patterns/ rel=tag>Design Patterns</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Disruptor/ rel=tag>Disruptor</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/Distributed-Lock/ rel=tag>Distributed Lock</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Docker/ rel=tag>Docker</a><span class=tag-list-count>5</span><li class=tag-list-item><a class=tag-list-link href=/tags/Dockerfile/ rel=tag>Dockerfile</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Druid/ rel=tag>Druid</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Dubbo/ rel=tag>Dubbo</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/EagerThreadPool/ rel=tag>EagerThreadPool</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Evict/ rel=tag>Evict</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Filter/ rel=tag>Filter</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/First-Bad-Version/ rel=tag>First Bad Version</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/FixedThreadPool/ rel=tag>FixedThreadPool</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/G1/ rel=tag>G1</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/GC/ rel=tag>GC</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Garbage-First-Collector/ rel=tag>Garbage-First Collector</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Gogs/ rel=tag>Gogs</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Homebrew/ rel=tag>Homebrew</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Inorder-Traversal/ rel=tag>Inorder Traversal</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Interceptor/ rel=tag>Interceptor</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Intersection-of-Two-Arrays/ rel=tag>Intersection of Two Arrays</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/JMap/ rel=tag>JMap</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/JPS/ rel=tag>JPS</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/JStack/ rel=tag>JStack</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/JVM/ rel=tag>JVM</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/Java/ rel=tag>Java</a><span class=tag-list-count>50</span><li class=tag-list-item><a class=tag-list-link href=/tags/Leetcode-42/ rel=tag>Leetcode 42</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/LimitedThreadPool/ rel=tag>LimitedThreadPool</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Linked-List/ rel=tag>Linked List</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/Lowest-Common-Ancestor-of-a-Binary-Tree/ rel=tag>Lowest Common Ancestor of a Binary Tree</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/MQ/ rel=tag>MQ</a><span class=tag-list-count>9</span><li class=tag-list-item><a class=tag-list-link href=/tags/Mac/ rel=tag>Mac</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Maven/ rel=tag>Maven</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Median-of-Two-Sorted-Arrays/ rel=tag>Median of Two Sorted Arrays</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Mybatis/ rel=tag>Mybatis</a><span class=tag-list-count>13</span><li class=tag-list-item><a class=tag-list-link href=/tags/Mysql/ rel=tag>Mysql</a><span class=tag-list-count>13</span><li class=tag-list-item><a class=tag-list-link href=/tags/NameServer/ rel=tag>NameServer</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/PHP/ rel=tag>PHP</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Preorder-Traversal/ rel=tag>Preorder Traversal</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Print-FooBar-Alternately/ rel=tag>Print FooBar Alternately</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/RPC/ rel=tag>RPC</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/Redis/ rel=tag>Redis</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/Remove-Duplicates-from-Sorted-List/ rel=tag>Remove Duplicates from Sorted List</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/RocketMQ/ rel=tag>RocketMQ</a><span class=tag-list-count>9</span><li class=tag-list-item><a class=tag-list-link href=/tags/Rotate-Image/ rel=tag>Rotate Image</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Rust/ rel=tag>Rust</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/SPI/ rel=tag>SPI</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/Servlet/ rel=tag>Servlet</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Sharding-Jdbc/ rel=tag>Sharding-Jdbc</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/Shift-2D-Grid/ rel=tag>Shift 2D Grid</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Singleton/ rel=tag>Singleton</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Spring/ rel=tag>Spring</a><span class=tag-list-count>7</span><li class=tag-list-item><a class=tag-list-link href=/tags/Spring-Event/ rel=tag>Spring Event</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/SpringBoot/ rel=tag>SpringBoot</a><span class=tag-list-count>10</span><li class=tag-list-item><a class=tag-list-link href=/tags/Sql%E6%B3%A8%E5%85%A5/ rel=tag>Sql注入</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Stream/ rel=tag>Stream</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Synchronized/ rel=tag>Synchronized</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/Thread-dump/ rel=tag>Thread dump</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/ThreadLocal/ rel=tag>ThreadLocal</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/ThreadPool/ rel=tag>ThreadPool</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Tomcat/ rel=tag>Tomcat</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Trapping-Rain-Water/ rel=tag>Trapping Rain Water</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/WeakReference/ rel=tag>WeakReference</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Web/ rel=tag>Web</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Webhook/ rel=tag>Webhook</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Windows/ rel=tag>Windows</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/WordPress/ rel=tag>WordPress</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/aqs/ rel=tag>aqs</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/await/ rel=tag>await</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/bloom-filter/ rel=tag>bloom filter</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/c/ rel=tag>c++</a><span class=tag-list-count>14</span><li class=tag-list-item><a class=tag-list-link href=/tags/cglib/ rel=tag>cglib</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/cgroup/ rel=tag>cgroup</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/cluster/ rel=tag>cluster</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/condition/ rel=tag>condition</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/dnsmasq/ rel=tag>dnsmasq</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/docker/ rel=tag>docker</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/dp/ rel=tag>dp</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/dubbo/ rel=tag>dubbo</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/echo/ rel=tag>echo</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/environment/ rel=tag>environment</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/gap-lock/ rel=tag>gap lock</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/gc/ rel=tag>gc</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/git/ rel=tag>git</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/grep/ rel=tag>grep</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/hadoop/ rel=tag>hadoop</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/headscale/ rel=tag>headscale</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/hexo/ rel=tag>hexo</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/icu4c/ rel=tag>icu4c</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/im/ rel=tag>im</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/is-not-null/ rel=tag>is not null</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/is-null/ rel=tag>is null</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/j-u-c/ rel=tag>j.u.c</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/java/ rel=tag>java</a><span class=tag-list-count>35</span><li class=tag-list-item><a class=tag-list-link href=/tags/jvm/ rel=tag>jvm</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/leetcode/ rel=tag>leetcode</a><span class=tag-list-count>40</span><li class=tag-list-item><a class=tag-list-link href=/tags/leetcode-155/ rel=tag>leetcode 155</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/linked-list/ rel=tag>linked list</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/linux/ rel=tag>linux</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/lock/ rel=tag>lock</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/mfc/ rel=tag>mfc</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/min-stack/ rel=tag>min stack</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/mq/ rel=tag>mq</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/mvcc/ rel=tag>mvcc</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/mysql/ rel=tag>mysql</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/namespace/ rel=tag>namespace</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/nas/ rel=tag>nas</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/next-key-lock/ rel=tag>next-key lock</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/nginx/ rel=tag>nginx</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/nullsfirst/ rel=tag>nullsfirst</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/openresty/ rel=tag>openresty</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/php/ rel=tag>php</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/powershell/ rel=tag>powershell</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/procedure/ rel=tag>procedure</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/python/ rel=tag>python</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/read-view/ rel=tag>read view</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/redis/ rel=tag>redis</a><span class=tag-list-count>12</span><li class=tag-list-item><a class=tag-list-link href=/tags/scp/ rel=tag>scp</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/signal/ rel=tag>signal</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/sort/ rel=tag>sort</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/spark/ rel=tag>spark</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/ssh/ rel=tag>ssh</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/stack/ rel=tag>stack</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/stream/ rel=tag>stream</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/string/ rel=tag>string</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/swoole/ rel=tag>swoole</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/top/ rel=tag>top</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/uname/ rel=tag>uname</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/unlock/ rel=tag>unlock</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8/ rel=tag>utf8</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4/ rel=tag>utf8mb4</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4-0900-ai-ci/ rel=tag>utf8mb4_0900_ai_ci</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4-general-ci/ rel=tag>utf8mb4_general_ci</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4-unicode-ci/ rel=tag>utf8mb4_unicode_ci</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/value/ rel=tag>value</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/websocket/ rel=tag>websocket</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/windows/ rel=tag>windows</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/wsl/ rel=tag>wsl</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/zookeeper/ rel=tag>zookeeper</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/zsh/ rel=tag>zsh</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ rel=tag>三阶段提交</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%8D%E5%8F%AF%E5%8F%98%E5%BC%95%E7%94%A8/ rel=tag>不可变引用</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%9C%E4%BA%AC%E5%A5%A5%E8%BF%90%E4%BC%9A/ rel=tag>东京奥运会</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ rel=tag>两阶段提交</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%AD%E5%B1%B1%E8%B7%AF/ rel=tag>中山路</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%AD%E5%BA%8F/ rel=tag>中序</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%AD%E9%97%B4%E4%BB%B6/ rel=tag>中间件</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%BE%E9%87%8D/ rel=tag>举重</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B9%92%E4%B9%93%E7%90%83/ rel=tag>乒乓球</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BA%8B%E5%8A%A1/ rel=tag>事务</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BA%8C%E5%8F%89%E6%A0%91/ rel=tag>二叉树</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BA%92%E6%96%A5%E9%94%81/ rel=tag>互斥锁</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BB%A3%E7%A0%81%E9%A2%98%E8%A7%A3/ rel=tag>代码题解</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BF%AE%E7%94%B5%E8%84%91%E7%9A%84/ rel=tag>修电脑的</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%81%8F%E5%90%91%E9%94%81/ rel=tag>偏向锁</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%81%A5%E5%BA%B7%E7%A0%81/ rel=tag>健康码</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%85%AC%E4%BA%A4/ rel=tag>公交</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%85%AC%E4%BA%A4%E8%BD%A6/ rel=tag>公交车</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%86%85%E5%AD%98%E5%88%86%E5%B8%83/ rel=tag>内存分布</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/ rel=tag>内存泄漏</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%87%86%E5%A4%87/ rel=tag>准备</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%87%8F%E8%82%A5/ rel=tag>减肥</a><span class=tag-list-count>7</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ rel=tag>分布式事务</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/ rel=tag>分布式锁</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%87%E7%89%87/ rel=tag>切片</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%9D%E5%A7%8B%E5%8C%96/ rel=tag>初始化</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%89%8A%E5%B3%B0%E5%A1%AB%E8%B0%B7/ rel=tag>削峰填谷</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%89%8D%E5%BA%8F/ rel=tag>前序</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8A%A0%E5%A1%9E/ rel=tag>加塞</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8A%A0%E8%BD%BD/ rel=tag>加载</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8D%95%E4%BE%8B/ rel=tag>单例</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8D%9A%E5%AE%A2%EF%BC%8C%E6%96%87%E7%AB%A0/ rel=tag>博客,文章</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8E%A6%E9%97%A8/ rel=tag>厦门</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE/ rel=tag>双亲委派</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%91%E8%A1%8C%E7%89%88/ rel=tag>发行版</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%A3%E7%BD%A9/ rel=tag>口罩</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%AF%E5%8F%98%E5%BC%95%E7%94%A8/ rel=tag>可变引用</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%90%90%E6%A7%BD/ rel=tag>吐槽</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%9B%A4%E7%89%A9%E8%B5%84/ rel=tag>囤物资</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6/ rel=tag>垃圾回收</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%9F%BA%E7%A1%80%E8%AE%BE%E6%96%BD/ rel=tag>基础设施</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%A4%A7%E6%89%AB%E9%99%A4/ rel=tag>大扫除</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AD%97%E7%AC%A6%E9%9B%86/ rel=tag>字符集</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AE%89%E5%85%A8/ rel=tag>安全</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B6/ rel=tag>容错机制</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AF%84%E7%94%9F%E8%99%AB/ rel=tag>寄生虫</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B0%84%E5%87%BB/ rel=tag>射击</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B0%8F%E6%8A%80%E5%B7%A7/ rel=tag>小技巧</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B1%80%E5%8F%A3%E8%A1%97/ rel=tag>局口街</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8/ rel=tag>布隆过滤器</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B2%E6%B4%BB/ rel=tag>干活</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/ rel=tag>年中总结</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ rel=tag>年终总结</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B6%E5%8F%91/ rel=tag>并发</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B8%E7%A6%8F%E4%BA%86%E5%90%97/ rel=tag>幸福了吗</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%BB%E8%AF%BB/ rel=tag>幻读</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BA%94%E7%94%A8/ rel=tag>应用</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BC%80%E8%BD%A6/ rel=tag>开车</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BC%B1%E5%BC%95%E7%94%A8/ rel=tag>弱引用</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BD%B1%E8%AF%84/ rel=tag>影评</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%89%80%E6%9C%89%E6%9D%83/ rel=tag>所有权</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%89%93%E5%8D%A1/ rel=tag>打卡</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%89%B6%E6%A2%AF/ rel=tag>扶梯</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8A%80%E6%9C%AF/ rel=tag>技术</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8B%96%E6%9B%B4/ rel=tag>拖更</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8D%A2%E8%BD%A6%E7%89%8C/ rel=tag>换车牌</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8E%92%E5%BA%8F/ rel=tag>排序</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8E%A5%E9%9B%A8%E6%B0%B4/ rel=tag>接雨水</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%95%B0%E6%8D%AE%E6%BA%90%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2/ rel=tag>数据源动态切换</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ rel=tag>数据结构</a><span class=tag-list-count>11</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%96%B0%E8%AF%AD%E8%A8%80/ rel=tag>新语言</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%97%85%E6%B8%B8/ rel=tag>旅游</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%97%A5%E5%BF%97/ rel=tag>日志</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9B%BE%E5%8E%9D%E5%9E%B5/ rel=tag>曾厝垵</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9C%80%E5%B0%8F%E6%A0%88/ rel=tag>最小栈</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9D%80%E4%BA%BA%E8%AF%9B%E5%BF%83/ rel=tag>杀人诛心</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9D%AD%E5%B7%9E/ rel=tag>杭州</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%A0%87%E8%AE%B0%E6%95%B4%E7%90%86/ rel=tag>标记整理</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%A4%8D%E7%89%A9%E5%9B%AD/ rel=tag>植物园</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B2%99%E8%8C%B6%E9%9D%A2/ rel=tag>沙茶面</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B3%A8%E8%A7%A3/ rel=tag>注解</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B5%B7%E8%9B%8E%E7%85%8E/ rel=tag>海蛎煎</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/ rel=tag>消息队列</a><span class=tag-list-count>9</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B7%98%E6%B1%B0%E7%AD%96%E7%95%A5/ rel=tag>淘汰策略</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/ rel=tag>深度学习</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%BA%90%E7%A0%81/ rel=tag>源码</a><span class=tag-list-count>11</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/ rel=tag>源码解析</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%94%9F%E6%B4%BB/ rel=tag>生活</a><span class=tag-list-count>42</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%94%B5%E7%93%B6%E8%BD%A6/ rel=tag>电瓶车</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%96%AB%E6%83%85/ rel=tag>疫情</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%9C%8B%E4%B9%A6/ rel=tag>看书</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%9C%8B%E5%89%A7/ rel=tag>看剧</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%9F%A9%E9%98%B5/ rel=tag>矩阵</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%AB%AF%E5%8F%A3%E8%BD%AC%E5%8F%91/ rel=tag>端口转发</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%B1%BB%E5%8A%A0%E8%BD%BD/ rel=tag>类加载</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%B3%9F%E5%BF%83%E4%BA%8B/ rel=tag>糟心事</a><span class=tag-list-count>5</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%B4%A2%E5%BC%95/ rel=tag>索引</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%BA%BF%E7%A8%8B%E6%B1%A0/ rel=tag>线程池</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%BC%93%E5%AD%98/ rel=tag>缓存</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF/ rel=tag>缓存击穿</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F/ rel=tag>缓存穿透</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9/ rel=tag>缓存雪崩</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%BC%96%E7%A0%81/ rel=tag>编码</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E7%BE%8E%E5%9B%BD/ rel=tag>美国</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%80%81%E7%94%B5%E8%84%91/ rel=tag>老电脑</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D/ rel=tag>自动装配</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%87%AA%E6%97%8B/ rel=tag>自旋</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%87%AA%E9%80%82%E5%BA%94%E6%8B%93%E5%B1%95/ rel=tag>自适应拓展</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%A3%85%E7%94%B5%E8%84%91/ rel=tag>装电脑</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%A7%84%E5%88%99/ rel=tag>规则</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%A7%A3%E6%9E%90/ rel=tag>解析</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/ rel=tag>设计模式</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%AF%BB%E4%B9%A6/ rel=tag>读书</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%AF%BB%E5%90%8E%E6%84%9F/ rel=tag>读后感</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/ rel=tag>负载均衡</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B6%B3%E7%90%83/ rel=tag>足球</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B7%91%E6%AD%A5/ rel=tag>跑步</a><span class=tag-list-count>7</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B7%AF%E6%94%BF%E8%A7%84%E5%88%92/ rel=tag>路政规划</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B7%AF%E7%94%B1%E5%99%A8/ rel=tag>路由器</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B7%B3%E6%B0%B4/ rel=tag>跳水</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B8%A9%E8%B8%8F/ rel=tag>踩踏</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BD%AC%E4%B9%89/ rel=tag>转义</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BD%BB%E9%87%8F%E7%BA%A7%E9%94%81/ rel=tag>轻量级锁</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BF%87%E6%9C%9F%E7%AD%96%E7%95%A5/ rel=tag>过期策略</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BF%90%E5%8A%A8/ rel=tag>运动</a><span class=tag-list-count>9</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BF%9C%E7%A8%8B%E5%8A%9E%E5%85%AC/ rel=tag>远程办公</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%80%92%E5%BD%92/ rel=tag>递归</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%87%8D%E9%87%8F%E7%BA%A7%E9%94%81/ rel=tag>重量级锁</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%93%BE%E6%8E%A5/ rel=tag>链接</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%A2%98%E8%A7%A3/ rel=tag>题解</a><span class=tag-list-count>24</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%A9%AC%E6%88%8F%E5%9B%A2/ rel=tag>马戏团</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%AA%8C%E8%AF%81/ rel=tag>验证</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%AA%91%E8%BD%A6/ rel=tag>骑车</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%AB%98%E9%80%9F/ rel=tag>高速</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%BC%93%E6%B5%AA%E5%B1%BF/ rel=tag>鼓浪屿</a><span class=tag-list-count>1</span></ul></canvas></div></div></div></div></div><div class="sidebar-inner sidebar-blogroll"><div class="links-of-blogroll animated"><div class=links-of-blogroll-title><i class="fa fa-globe fa-fw"></i> 链接</div><ul class=links-of-blogroll-list><li class=links-of-blogroll-item><a href=https://covermusic.cn/ rel=noopener target=_blank title=https://covermusic.cn>69伙伴</a></ul></div></div></aside></div><div class="main-inner index posts-expand"><div class=post-block><article class=post-content itemscope itemtype=http://schema.org/Article><link href=https://nicksxs.me/2022/09/25/Disruptor-%E7%B3%BB%E5%88%97%E4%B8%89/ itemprop=mainEntityOfPage><span hidden itemprop=author itemscope itemtype=http://schema.org/Person><meta content=/uploads/avatar.jpg itemprop=image><meta content=Nicksxs itemprop=name></span><span hidden itemprop=publisher itemscope itemtype=http://schema.org/Organization><meta content="Nicksxs's Blog" itemprop=name><meta content="learn from zero,技术博客,Nicksxs,史学森" itemprop=description></span><span hidden itemprop=post itemscope itemtype=http://schema.org/CreativeWork><meta content="undefined | Nicksxs's Blog" itemprop=name><meta itemprop=description></span><header class=post-header><h2 itemprop="name headline" class=post-title><a class=post-title-link href=/2022/09/25/Disruptor-%E7%B3%BB%E5%88%97%E4%B8%89/ itemprop=url>Disruptor 系列三</a></h2><div class=post-meta-container><div class=post-meta><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-calendar"></i> </span><span class=post-meta-item-text>发表于</span> <time itemprop="dateCreated datePublished" title="创建时间:2022-09-25 21:17:28" datetime=2022-09-25T21:17:28+08:00>2022-09-25</time> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-folder"></i> </span><span class=post-meta-item-text>分类于</span> <span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/ itemprop=url rel=index><span itemprop=name>Java</span></a> </span></span><span class="post-meta-item leancloud_visitors" data-flag-title="Disruptor 系列三" id=/2022/09/25/Disruptor-%E7%B3%BB%E5%88%97%E4%B8%89/ title=阅读次数><span class=post-meta-item-icon><i class="far fa-eye"></i> </span><span class=post-meta-item-text>阅读次数:</span> <span class=leancloud-visitors-count></span> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-comment"></i> </span><span class=post-meta-item-text>Disqus:</span> <a href=/2022/09/25/Disruptor-%E7%B3%BB%E5%88%97%E4%B8%89/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2022/09/25/Disruptor-系列三/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>原来一直有点被误导,<br>gatingSequences用来标识每个 processer 的操作位点,但是怎么记录更新有点搞不清楚<br>其实问题在于 gatingSequences 是个 Sequence 数组,首先要看下怎么加进去的,<br>可以看到是在 <code>com.lmax.disruptor.RingBuffer#addGatingSequences</code> 这个方法里添加<br>首先是 <code>com.lmax.disruptor.dsl.Disruptor#handleEventsWith(com.lmax.disruptor.EventHandler&LT? super T>...)</code><br>然后执行 <code>com.lmax.disruptor.dsl.Disruptor#createEventProcessors(com.lmax.disruptor.Sequence[], com.lmax.disruptor.EventHandler&LT? super T>[])</code><pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name">EventHandlerGroup</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">T</span><span class="token punctuation">></span></span> <span class="token function">createEventProcessors</span><span class="token punctuation">(</span>
<span class="token keyword">final</span> <span class="token class-name">Sequence</span><span class="token punctuation">[</span><span class="token punctuation">]</span> barrierSequences<span class="token punctuation">,</span>
<span class="token keyword">final</span> <span class="token class-name">EventHandler</span><span class="token generics"><span class="token punctuation"><</span><span class="token operator">?</span> <span class="token keyword">super</span> <span class="token class-name">T</span><span class="token punctuation">></span></span><span class="token punctuation">[</span><span class="token punctuation">]</span> eventHandlers<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">checkNotStarted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">final</span> <span class="token class-name">Sequence</span><span class="token punctuation">[</span><span class="token punctuation">]</span> processorSequences <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Sequence</span><span class="token punctuation">[</span>eventHandlers<span class="token punctuation">.</span>length<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">final</span> <span class="token class-name">SequenceBarrier</span> barrier <span class="token operator">=</span> ringBuffer<span class="token punctuation">.</span><span class="token function">newBarrier</span><span class="token punctuation">(</span>barrierSequences<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> eventHandlersLength <span class="token operator">=</span> eventHandlers<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator"><</span> eventHandlersLength<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">final</span> <span class="token class-name">EventHandler</span><span class="token generics"><span class="token punctuation"><</span><span class="token operator">?</span> <span class="token keyword">super</span> <span class="token class-name">T</span><span class="token punctuation">></span></span> eventHandler <span class="token operator">=</span> eventHandlers<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// 这里将 handler 包装成一个 BatchEventProcessor</span>
<span class="token keyword">final</span> <span class="token class-name">BatchEventProcessor</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">T</span><span class="token punctuation">></span></span> batchEventProcessor <span class="token operator">=</span>
<span class="token keyword">new</span> <span class="token class-name">BatchEventProcessor</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span>ringBuffer<span class="token punctuation">,</span> barrier<span class="token punctuation">,</span> eventHandler<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>exceptionHandler <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
batchEventProcessor<span class="token punctuation">.</span><span class="token function">setExceptionHandler</span><span class="token punctuation">(</span>exceptionHandler<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
consumerRepository<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>batchEventProcessor<span class="token punctuation">,</span> eventHandler<span class="token punctuation">,</span> barrier<span class="token punctuation">)</span><span class="token punctuation">;</span>
processorSequences<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> batchEventProcessor<span class="token punctuation">.</span><span class="token function">getSequence</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">updateGatingSequencesForNextInChain</span><span class="token punctuation">(</span>barrierSequences<span class="token punctuation">,</span> processorSequences<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">EventHandlerGroup</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> consumerRepository<span class="token punctuation">,</span> processorSequences<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p><code>BatchEventProcessor</code> 在类内有个定义 sequence<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">private</span> <span class="token keyword">final</span> <span class="token class-name">Sequence</span> sequence <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Sequence</span><span class="token punctuation">(</span><span class="token class-name">Sequencer</span><span class="token punctuation">.</span><span class="token constant">INITIAL_CURSOR_VALUE</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden=true class=line-numbers-rows><span></span></span></code></pre><p>然后在上面循环中的这一句取出来<pre class="line-numbers language-java" data-language=java><code class=language-java>processorSequences<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> batchEventProcessor<span class="token punctuation">.</span><span class="token function">getSequence</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden=true class=line-numbers-rows><span></span></span></code></pre><p>调用<code>com.lmax.disruptor.dsl.Disruptor#updateGatingSequencesForNextInChain</code> 方法<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">updateGatingSequencesForNextInChain</span><span class="token punctuation">(</span><span class="token keyword">final</span> <span class="token class-name">Sequence</span><span class="token punctuation">[</span><span class="token punctuation">]</span> barrierSequences<span class="token punctuation">,</span> <span class="token keyword">final</span> <span class="token class-name">Sequence</span><span class="token punctuation">[</span><span class="token punctuation">]</span> processorSequences<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>processorSequences<span class="token punctuation">.</span>length <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment">// 然后在这里添加</span>
ringBuffer<span class="token punctuation">.</span><span class="token function">addGatingSequences</span><span class="token punctuation">(</span>processorSequences<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">final</span> <span class="token class-name">Sequence</span> barrierSequence <span class="token operator">:</span> barrierSequences<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
ringBuffer<span class="token punctuation">.</span><span class="token function">removeGatingSequence</span><span class="token punctuation">(</span>barrierSequence<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
consumerRepository<span class="token punctuation">.</span><span class="token function">unMarkEventProcessorsAsEndOfChain</span><span class="token punctuation">(</span>barrierSequences<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>而如何更新则是在处理器 <code>com.lmax.disruptor.BatchEventProcessor#run</code><pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>running<span class="token punctuation">.</span><span class="token function">compareAndSet</span><span class="token punctuation">(</span><span class="token constant">IDLE</span><span class="token punctuation">,</span> <span class="token constant">RUNNING</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
sequenceBarrier<span class="token punctuation">.</span><span class="token function">clearAlert</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">notifyStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>running<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">RUNNING</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">processEvents</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">finally</span>
<span class="token punctuation">{</span>
<span class="token function">notifyShutdown</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
running<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token constant">IDLE</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
<span class="token punctuation">{</span>
<span class="token comment">// This is a little bit of guess work. The running state could of changed to HALTED by</span>
<span class="token comment">// this point. However, Java does not have compareAndExchange which is the only way</span>
<span class="token comment">// to get it exactly correct.</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>running<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token constant">RUNNING</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalStateException</span><span class="token punctuation">(</span><span class="token string">"Thread is already running"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
<span class="token punctuation">{</span>
<span class="token function">earlyExit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后是<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">processEvents</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token class-name">T</span> event <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">long</span> nextSequence <span class="token operator">=</span> sequence<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1L</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">try</span>
<span class="token punctuation">{</span>
<span class="token keyword">final</span> <span class="token keyword">long</span> availableSequence <span class="token operator">=</span> sequenceBarrier<span class="token punctuation">.</span><span class="token function">waitFor</span><span class="token punctuation">(</span>nextSequence<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>batchStartAware <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
batchStartAware<span class="token punctuation">.</span><span class="token function">onBatchStart</span><span class="token punctuation">(</span>availableSequence <span class="token operator">-</span> nextSequence <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>nextSequence <span class="token operator"><=</span> availableSequence<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
event <span class="token operator">=</span> dataProvider<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>nextSequence<span class="token punctuation">)</span><span class="token punctuation">;</span>
eventHandler<span class="token punctuation">.</span><span class="token function">onEvent</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span> nextSequence<span class="token punctuation">,</span> nextSequence <span class="token operator">==</span> availableSequence<span class="token punctuation">)</span><span class="token punctuation">;</span>
nextSequence<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 如果正常处理完,那就是会更新为 availableSequence,因为都处理好了</span>
sequence<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>availableSequence<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token keyword">final</span> <span class="token class-name">TimeoutException</span> e<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">notifyTimeout</span><span class="token punctuation">(</span>sequence<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token keyword">final</span> <span class="token class-name">AlertException</span> ex<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>running<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token constant">RUNNING</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token keyword">final</span> <span class="token class-name">Throwable</span> ex<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">handleEventException</span><span class="token punctuation">(</span>ex<span class="token punctuation">,</span> nextSequence<span class="token punctuation">,</span> event<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 如果是异常就只是 nextSequence</span>
sequence<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>nextSequence<span class="token punctuation">)</span><span class="token punctuation">;</span>
nextSequence<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div><footer class=post-footer><div class=post-eof></div></footer></article></div><div class=post-block><article class=post-content itemscope itemtype=http://schema.org/Article><link href=https://nicksxs.me/2022/09/18/Apollo-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/ itemprop=mainEntityOfPage><span hidden itemprop=author itemscope itemtype=http://schema.org/Person><meta content=/uploads/avatar.jpg itemprop=image><meta content=Nicksxs itemprop=name></span><span hidden itemprop=publisher itemscope itemtype=http://schema.org/Organization><meta content="Nicksxs's Blog" itemprop=name><meta content="learn from zero,技术博客,Nicksxs,史学森" itemprop=description></span><span hidden itemprop=post itemscope itemtype=http://schema.org/CreativeWork><meta content="undefined | Nicksxs's Blog" itemprop=name><meta itemprop=description></span><header class=post-header><h2 itemprop="name headline" class=post-title><a class=post-title-link href=/2022/09/18/Apollo-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/ itemprop=url>Apollo 客户端启动过程分析</a></h2><div class=post-meta-container><div class=post-meta><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-calendar"></i> </span><span class=post-meta-item-text>发表于</span> <time itemprop="dateCreated datePublished" title="创建时间:2022-09-18 21:15:12" datetime=2022-09-18T21:15:12+08:00>2022-09-18</time> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-folder"></i> </span><span class=post-meta-item-text>分类于</span> <span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/ itemprop=url rel=index><span itemprop=name>Java</span></a> </span></span><span class="post-meta-item leancloud_visitors" data-flag-title="Apollo 客户端启动过程分析" id=/2022/09/18/Apollo-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/ title=阅读次数><span class=post-meta-item-icon><i class="far fa-eye"></i> </span><span class=post-meta-item-text>阅读次数:</span> <span class=leancloud-visitors-count></span> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-comment"></i> </span><span class=post-meta-item-text>Disqus:</span> <a href=/2022/09/18/Apollo-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E8%BF%87%E7%A8%8B%E5%88%86%E6%9E%90/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2022/09/18/Apollo-客户端启动过程分析/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>入口是可以在 springboot 的启动类上打上<code>EnableApolloConfig</code>注解<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token annotation punctuation">@Import</span><span class="token punctuation">(</span><span class="token class-name">ApolloConfigRegistrar</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@interface</span> <span class="token class-name">EnableApolloConfig</span> <span class="token punctuation">{</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span></span></code></pre><p>这个 import 实现了<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ApolloConfigRegistrar</span> <span class="token keyword">implements</span> <span class="token class-name">ImportBeanDefinitionRegistrar</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token class-name">ApolloConfigRegistrarHelper</span> helper <span class="token operator">=</span> <span class="token class-name">ServiceBootstrap</span><span class="token punctuation">.</span><span class="token function">loadPrimary</span><span class="token punctuation">(</span><span class="token class-name">ApolloConfigRegistrarHelper</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">registerBeanDefinitions</span><span class="token punctuation">(</span><span class="token class-name">AnnotationMetadata</span> importingClassMetadata<span class="token punctuation">,</span> <span class="token class-name">BeanDefinitionRegistry</span> registry<span class="token punctuation">)</span> <span class="token punctuation">{</span>
helper<span class="token punctuation">.</span><span class="token function">registerBeanDefinitions</span><span class="token punctuation">(</span>importingClassMetadata<span class="token punctuation">,</span> registry<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后就调用了<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>spring<span class="token punctuation">.</span>spi<span class="token punctuation">.</span></span>DefaultApolloConfigRegistrarHelper</span>#registerBeanDefinitions<span aria-hidden=true class=line-numbers-rows><span></span></span></code></pre><p>接着是注册了这个 bean,com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">registerBeanDefinitions</span><span class="token punctuation">(</span><span class="token class-name">AnnotationMetadata</span> importingClassMetadata<span class="token punctuation">,</span> <span class="token class-name">BeanDefinitionRegistry</span> registry<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">AnnotationAttributes</span> attributes <span class="token operator">=</span> <span class="token class-name">AnnotationAttributes</span>
<span class="token punctuation">.</span><span class="token function">fromMap</span><span class="token punctuation">(</span>importingClassMetadata<span class="token punctuation">.</span><span class="token function">getAnnotationAttributes</span><span class="token punctuation">(</span><span class="token class-name">EnableApolloConfig</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> namespaces <span class="token operator">=</span> attributes<span class="token punctuation">.</span><span class="token function">getStringArray</span><span class="token punctuation">(</span><span class="token string">"value"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> order <span class="token operator">=</span> attributes<span class="token punctuation">.</span><span class="token function">getNumber</span><span class="token punctuation">(</span><span class="token string">"order"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">PropertySourcesProcessor</span><span class="token punctuation">.</span><span class="token function">addNamespaces</span><span class="token punctuation">(</span><span class="token class-name">Lists</span><span class="token punctuation">.</span><span class="token function">newArrayList</span><span class="token punctuation">(</span>namespaces<span class="token punctuation">)</span><span class="token punctuation">,</span> order<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">></span></span> propertySourcesPlaceholderPropertyValues <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashMap</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer</span>
propertySourcesPlaceholderPropertyValues<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span><span class="token string">"order"</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">BeanRegistrationUtil</span><span class="token punctuation">.</span><span class="token function">registerBeanDefinitionIfNotExists</span><span class="token punctuation">(</span>registry<span class="token punctuation">,</span> <span class="token class-name">PropertySourcesPlaceholderConfigurer</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token class-name">PropertySourcesPlaceholderConfigurer</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> propertySourcesPlaceholderPropertyValues<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 注册了这个 bean</span>
<span class="token class-name">BeanRegistrationUtil</span><span class="token punctuation">.</span><span class="token function">registerBeanDefinitionIfNotExists</span><span class="token punctuation">(</span>registry<span class="token punctuation">,</span> <span class="token class-name">PropertySourcesProcessor</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token class-name">PropertySourcesProcessor</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>而com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor 实现了 org.springframework.beans.factory.config.BeanFactoryPostProcessor<br>它里面的 com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor#postProcessBeanFactory 方法就会被 spring 调用,<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">initializePropertySources</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>environment<span class="token punctuation">.</span><span class="token function">getPropertySources</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">contains</span><span class="token punctuation">(</span><span class="token class-name">PropertySourcesConstants</span><span class="token punctuation">.</span><span class="token constant">APOLLO_PROPERTY_SOURCE_NAME</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//already initialized</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token class-name">CompositePropertySource</span> composite <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">CompositePropertySource</span><span class="token punctuation">(</span><span class="token class-name">PropertySourcesConstants</span><span class="token punctuation">.</span><span class="token constant">APOLLO_PROPERTY_SOURCE_NAME</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//sort by order asc</span>
<span class="token class-name">ImmutableSortedSet</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Integer</span><span class="token punctuation">></span></span> orders <span class="token operator">=</span> <span class="token class-name">ImmutableSortedSet</span><span class="token punctuation">.</span><span class="token function">copyOf</span><span class="token punctuation">(</span><span class="token constant">NAMESPACE_NAMES</span><span class="token punctuation">.</span><span class="token function">keySet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Iterator</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">Integer</span><span class="token punctuation">></span></span> iterator <span class="token operator">=</span> orders<span class="token punctuation">.</span><span class="token function">iterator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">hasNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> order <span class="token operator">=</span> iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">String</span> namespace <span class="token operator">:</span> <span class="token constant">NAMESPACE_NAMES</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>order<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 这里获取每个 namespace 的配置</span>
<span class="token class-name">Config</span> config <span class="token operator">=</span> <span class="token class-name">ConfigService</span><span class="token punctuation">.</span><span class="token function">getConfig</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
composite<span class="token punctuation">.</span><span class="token function">addPropertySource</span><span class="token punctuation">(</span>configPropertySourceFactory<span class="token punctuation">.</span><span class="token function">getConfigPropertySource</span><span class="token punctuation">(</span>namespace<span class="token punctuation">,</span> config<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后是 com.ctrip.framework.apollo.ConfigService#getConfig<br>接着就是它<br>com.ctrip.framework.apollo.internals.DefaultConfigManager#getConfig<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token class-name">Config</span> <span class="token function">getConfig</span><span class="token punctuation">(</span><span class="token class-name">String</span> namespace<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Config</span> config <span class="token operator">=</span> m_configs<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>config <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">synchronized</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
config <span class="token operator">=</span> m_configs<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>config <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">ConfigFactory</span> factory <span class="token operator">=</span> m_factoryManager<span class="token punctuation">.</span><span class="token function">getFactory</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 通过 factory 来创建配置获取</span>
config <span class="token operator">=</span> factory<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
m_configs<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span>namespace<span class="token punctuation">,</span> config<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>创建配置<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>spi<span class="token punctuation">.</span></span>DefaultConfigFactory</span>#create
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token class-name">Config</span> <span class="token function">create</span><span class="token punctuation">(</span><span class="token class-name">String</span> namespace<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">ConfigFileFormat</span> format <span class="token operator">=</span> <span class="token function">determineFileFormat</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">ConfigFileFormat</span><span class="token punctuation">.</span><span class="token function">isPropertiesCompatible</span><span class="token punctuation">(</span>format<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">DefaultConfig</span><span class="token punctuation">(</span>namespace<span class="token punctuation">,</span> <span class="token function">createPropertiesCompatibleFileConfigRepository</span><span class="token punctuation">(</span>namespace<span class="token punctuation">,</span> format<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 调用到这</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">DefaultConfig</span><span class="token punctuation">(</span>namespace<span class="token punctuation">,</span> <span class="token function">createLocalConfigRepository</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name">LocalFileConfigRepository</span> <span class="token function">createLocalConfigRepository</span><span class="token punctuation">(</span><span class="token class-name">String</span> namespace<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>m_configUtil<span class="token punctuation">.</span><span class="token function">isInLocalMode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span>
<span class="token string">"==== Apollo is in local mode! Won't pull configs from remote server for namespace {} ! ===="</span><span class="token punctuation">,</span>
namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">LocalFileConfigRepository</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 正常会走这个,因为要从配置中心获取</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">LocalFileConfigRepository</span><span class="token punctuation">(</span>namespace<span class="token punctuation">,</span> <span class="token function">createRemoteConfigRepository</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后是创建远程配置仓库<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>spi<span class="token punctuation">.</span></span>DefaultConfigFactory</span>#createRemoteConfigRepository
<span class="token class-name">RemoteConfigRepository</span> <span class="token function">createRemoteConfigRepository</span><span class="token punctuation">(</span><span class="token class-name">String</span> namespace<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">RemoteConfigRepository</span><span class="token punctuation">(</span>namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span></span></code></pre><p>继续对当前的 namespace 创建远程配置仓库<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>internals<span class="token punctuation">.</span></span>RemoteConfigRepository</span>#<span class="token class-name">RemoteConfigRepository</span>
<span class="token keyword">public</span> <span class="token class-name">RemoteConfigRepository</span><span class="token punctuation">(</span><span class="token class-name">String</span> namespace<span class="token punctuation">)</span> <span class="token punctuation">{</span>
m_namespace <span class="token operator">=</span> namespace<span class="token punctuation">;</span>
m_configCache <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AtomicReference</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_configUtil <span class="token operator">=</span> <span class="token class-name">ApolloInjector</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token class-name">ConfigUtil</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_httpUtil <span class="token operator">=</span> <span class="token class-name">ApolloInjector</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token class-name">HttpUtil</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_serviceLocator <span class="token operator">=</span> <span class="token class-name">ApolloInjector</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token class-name">ConfigServiceLocator</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
remoteConfigLongPollService <span class="token operator">=</span> <span class="token class-name">ApolloInjector</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token class-name">RemoteConfigLongPollService</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_longPollServiceDto <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AtomicReference</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_remoteMessages <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AtomicReference</span><span class="token generics"><span class="token punctuation"><</span><span class="token punctuation">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_loadConfigRateLimiter <span class="token operator">=</span> <span class="token class-name">RateLimiter</span><span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>m_configUtil<span class="token punctuation">.</span><span class="token function">getLoadConfigQPS</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_configNeedForceRefresh <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AtomicBoolean</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_loadConfigFailSchedulePolicy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ExponentialSchedulePolicy</span><span class="token punctuation">(</span>m_configUtil<span class="token punctuation">.</span><span class="token function">getOnErrorRetryInterval</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
m_configUtil<span class="token punctuation">.</span><span class="token function">getOnErrorRetryInterval</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
gson <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Gson</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 尝试同步</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">trySync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">schedulePeriodicRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">scheduleLongPollingRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后是同步配置,下面的日志异常经常可以看到,比如配置拉取地址不通<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>internals<span class="token punctuation">.</span></span>AbstractConfigRepository</span>#trySync
<span class="token keyword">protected</span> <span class="token keyword">boolean</span> <span class="token function">trySync</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token function">sync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">logEvent</span><span class="token punctuation">(</span><span class="token string">"ApolloConfigException"</span><span class="token punctuation">,</span> <span class="token class-name">ExceptionUtil</span><span class="token punctuation">.</span><span class="token function">getDetailMessage</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
logger
<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"Sync config failed, will retry. Repository {}, reason: {}"</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">ExceptionUtil</span>
<span class="token punctuation">.</span><span class="token function">getDetailMessage</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>实际的同步方法,加了<code>synchronized</code>锁,<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>internals<span class="token punctuation">.</span></span>RemoteConfigRepository</span>#sync
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">protected</span> <span class="token keyword">synchronized</span> <span class="token keyword">void</span> <span class="token function">sync</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Transaction</span> transaction <span class="token operator">=</span> <span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">newTransaction</span><span class="token punctuation">(</span><span class="token string">"Apollo.ConfigService"</span><span class="token punctuation">,</span> <span class="token string">"syncRemoteConfig"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 获取本地配置</span>
<span class="token class-name">ApolloConfig</span> previous <span class="token operator">=</span> m_configCache<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 获取配置</span>
<span class="token class-name">ApolloConfig</span> current <span class="token operator">=</span> <span class="token function">loadApolloConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//reference equals means HTTP 304</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>previous <span class="token operator">!=</span> current<span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Remote Config refreshed!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_configCache<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span>current<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">fireRepositoryChange</span><span class="token punctuation">(</span>m_namespace<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>current <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">logEvent</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"Apollo.Client.Configs.%s"</span><span class="token punctuation">,</span> current<span class="token punctuation">.</span><span class="token function">getNamespaceName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
current<span class="token punctuation">.</span><span class="token function">getReleaseKey</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
transaction<span class="token punctuation">.</span><span class="token function">setStatus</span><span class="token punctuation">(</span><span class="token class-name">Transaction</span><span class="token punctuation">.</span><span class="token constant">SUCCESS</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
transaction<span class="token punctuation">.</span><span class="token function">setStatus</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
transaction<span class="token punctuation">.</span><span class="token function">complete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>然后走到这<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>internals<span class="token punctuation">.</span></span>RemoteConfigRepository</span>#loadApolloConfig
<span class="token keyword">private</span> <span class="token class-name">ApolloConfig</span> <span class="token function">loadApolloConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>m_loadConfigRateLimiter<span class="token punctuation">.</span><span class="token function">tryAcquire</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">SECONDS</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//wait at most 5 seconds</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token class-name">TimeUnit</span><span class="token punctuation">.</span><span class="token constant">SECONDS</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token class-name">String</span> appId <span class="token operator">=</span> m_configUtil<span class="token punctuation">.</span><span class="token function">getAppId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> cluster <span class="token operator">=</span> m_configUtil<span class="token punctuation">.</span><span class="token function">getCluster</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> dataCenter <span class="token operator">=</span> m_configUtil<span class="token punctuation">.</span><span class="token function">getDataCenter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">logEvent</span><span class="token punctuation">(</span><span class="token string">"Apollo.Client.ConfigMeta"</span><span class="token punctuation">,</span> <span class="token constant">STRING_JOINER</span><span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>appId<span class="token punctuation">,</span> cluster<span class="token punctuation">,</span> m_namespace<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> maxRetries <span class="token operator">=</span> m_configNeedForceRefresh<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token number">2</span> <span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">long</span> onErrorSleepTime <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// 0 means no sleep</span>
<span class="token class-name">Throwable</span> exception <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token comment">// 获取配置</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">ServiceDTO</span><span class="token punctuation">></span></span> configServices <span class="token operator">=</span> <span class="token function">getConfigServices</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> url <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> maxRetries<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">ServiceDTO</span><span class="token punctuation">></span></span> randomConfigServices <span class="token operator">=</span> <span class="token class-name">Lists</span><span class="token punctuation">.</span><span class="token function">newLinkedList</span><span class="token punctuation">(</span>configServices<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">shuffle</span><span class="token punctuation">(</span>randomConfigServices<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">//Access the server which notifies the client first</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>m_longPollServiceDto<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
randomConfigServices<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> m_longPollServiceDto<span class="token punctuation">.</span><span class="token function">getAndSet</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token class-name">ServiceDTO</span> configService <span class="token operator">:</span> randomConfigServices<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>onErrorSleepTime <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span>
<span class="token string">"Load config failed, will retry in {} {}. appId: {}, cluster: {}, namespaces: {}"</span><span class="token punctuation">,</span>
onErrorSleepTime<span class="token punctuation">,</span> m_configUtil<span class="token punctuation">.</span><span class="token function">getOnErrorRetryIntervalTimeUnit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> appId<span class="token punctuation">,</span> cluster<span class="token punctuation">,</span> m_namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
m_configUtil<span class="token punctuation">.</span><span class="token function">getOnErrorRetryIntervalTimeUnit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>onErrorSleepTime<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//ignore</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
url <span class="token operator">=</span> <span class="token function">assembleQueryConfigUrl</span><span class="token punctuation">(</span>configService<span class="token punctuation">.</span><span class="token function">getHomepageUrl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> appId<span class="token punctuation">,</span> cluster<span class="token punctuation">,</span> m_namespace<span class="token punctuation">,</span>
dataCenter<span class="token punctuation">,</span> m_remoteMessages<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> m_configCache<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
logger<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Loading config from {}"</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">HttpRequest</span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HttpRequest</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Transaction</span> transaction <span class="token operator">=</span> <span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">newTransaction</span><span class="token punctuation">(</span><span class="token string">"Apollo.ConfigService"</span><span class="token punctuation">,</span> <span class="token string">"queryConfig"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">addData</span><span class="token punctuation">(</span><span class="token string">"Url"</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token class-name">HttpResponse</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">ApolloConfig</span><span class="token punctuation">></span></span> response <span class="token operator">=</span> m_httpUtil<span class="token punctuation">.</span><span class="token function">doGet</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> <span class="token class-name">ApolloConfig</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_configNeedForceRefresh<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
m_loadConfigFailSchedulePolicy<span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">addData</span><span class="token punctuation">(</span><span class="token string">"StatusCode"</span><span class="token punctuation">,</span> response<span class="token punctuation">.</span><span class="token function">getStatusCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">setStatus</span><span class="token punctuation">(</span><span class="token class-name">Transaction</span><span class="token punctuation">.</span><span class="token constant">SUCCESS</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>response<span class="token punctuation">.</span><span class="token function">getStatusCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">304</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
logger<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Config server responds with 304 HTTP status code."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> m_configCache<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token class-name">ApolloConfig</span> result <span class="token operator">=</span> response<span class="token punctuation">.</span><span class="token function">getBody</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
logger<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Loaded config for {}: {}"</span><span class="token punctuation">,</span> m_namespace<span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">ApolloConfigStatusCodeException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">ApolloConfigStatusCodeException</span> statusCodeException <span class="token operator">=</span> ex<span class="token punctuation">;</span>
<span class="token comment">//config not found</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ex<span class="token punctuation">.</span><span class="token function">getStatusCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">404</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">String</span> message <span class="token operator">=</span> <span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>
<span class="token string">"Could not find config for namespace - appId: %s, cluster: %s, namespace: %s, "</span> <span class="token operator">+</span>
<span class="token string">"please check whether the configs are released in Apollo!"</span><span class="token punctuation">,</span>
appId<span class="token punctuation">,</span> cluster<span class="token punctuation">,</span> m_namespace<span class="token punctuation">)</span><span class="token punctuation">;</span>
statusCodeException <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ApolloConfigStatusCodeException</span><span class="token punctuation">(</span>ex<span class="token punctuation">.</span><span class="token function">getStatusCode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">logEvent</span><span class="token punctuation">(</span><span class="token string">"ApolloConfigException"</span><span class="token punctuation">,</span> <span class="token class-name">ExceptionUtil</span><span class="token punctuation">.</span><span class="token function">getDetailMessage</span><span class="token punctuation">(</span>statusCodeException<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">setStatus</span><span class="token punctuation">(</span>statusCodeException<span class="token punctuation">)</span><span class="token punctuation">;</span>
exception <span class="token operator">=</span> statusCodeException<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">logEvent</span><span class="token punctuation">(</span><span class="token string">"ApolloConfigException"</span><span class="token punctuation">,</span> <span class="token class-name">ExceptionUtil</span><span class="token punctuation">.</span><span class="token function">getDetailMessage</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">setStatus</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">;</span>
exception <span class="token operator">=</span> ex<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
transaction<span class="token punctuation">.</span><span class="token function">complete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// if force refresh, do normal sleep, if normal config load, do exponential sleep</span>
onErrorSleepTime <span class="token operator">=</span> m_configNeedForceRefresh<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">?</span> m_configUtil<span class="token punctuation">.</span><span class="token function">getOnErrorRetryInterval</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span>
m_loadConfigFailSchedulePolicy<span class="token punctuation">.</span><span class="token function">fail</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token class-name">String</span> message <span class="token operator">=</span> <span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span>
<span class="token string">"Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s, url: %s"</span><span class="token punctuation">,</span>
appId<span class="token punctuation">,</span> cluster<span class="token punctuation">,</span> m_namespace<span class="token punctuation">,</span> url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ApolloConfigException</span><span class="token punctuation">(</span>message<span class="token punctuation">,</span> exception<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>internals<span class="token punctuation">.</span></span>RemoteConfigRepository</span>#getConfigServices
<span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">ServiceDTO</span><span class="token punctuation">></span></span> <span class="token function">getConfigServices</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">ServiceDTO</span><span class="token punctuation">></span></span> services <span class="token operator">=</span> m_serviceLocator<span class="token punctuation">.</span><span class="token function">getConfigServices</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>services<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ApolloConfigException</span><span class="token punctuation">(</span><span class="token string">"No available config service"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> services<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>internals<span class="token punctuation">.</span></span>ConfigServiceLocator</span>#getConfigServices
<span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">ServiceDTO</span><span class="token punctuation">></span></span> <span class="token function">getConfigServices</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>m_configServices<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">updateConfigServices</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> m_configServices<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>更新配置服务<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name"><span class="token namespace">com<span class="token punctuation">.</span>ctrip<span class="token punctuation">.</span>framework<span class="token punctuation">.</span>apollo<span class="token punctuation">.</span>internals<span class="token punctuation">.</span></span>ConfigServiceLocator</span>#updateConfigServices
<span class="token keyword">private</span> <span class="token keyword">synchronized</span> <span class="token keyword">void</span> <span class="token function">updateConfigServices</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">String</span> url <span class="token operator">=</span> <span class="token function">assembleMetaServiceUrl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">HttpRequest</span> request <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HttpRequest</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> maxRetries <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">;</span>
<span class="token class-name">Throwable</span> exception <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> maxRetries<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Transaction</span> transaction <span class="token operator">=</span> <span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">newTransaction</span><span class="token punctuation">(</span><span class="token string">"Apollo.MetaService"</span><span class="token punctuation">,</span> <span class="token string">"getConfigService"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">addData</span><span class="token punctuation">(</span><span class="token string">"Url"</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 发起 http 请求获取配置</span>
<span class="token class-name">HttpResponse</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">List</span><span class="token punctuation"><</span><span class="token class-name">ServiceDTO</span><span class="token punctuation">></span><span class="token punctuation">></span></span> response <span class="token operator">=</span> m_httpUtil<span class="token punctuation">.</span><span class="token function">doGet</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> m_responseType<span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">setStatus</span><span class="token punctuation">(</span><span class="token class-name">Transaction</span><span class="token punctuation">.</span><span class="token constant">SUCCESS</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">ServiceDTO</span><span class="token punctuation">></span></span> services <span class="token operator">=</span> response<span class="token punctuation">.</span><span class="token function">getBody</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>services <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">||</span> services<span class="token punctuation">.</span><span class="token function">isEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">logConfigService</span><span class="token punctuation">(</span><span class="token string">"Empty response!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">continue</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">setConfigServices</span><span class="token punctuation">(</span>services<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Tracer</span><span class="token punctuation">.</span><span class="token function">logEvent</span><span class="token punctuation">(</span><span class="token string">"ApolloConfigException"</span><span class="token punctuation">,</span> <span class="token class-name">ExceptionUtil</span><span class="token punctuation">.</span><span class="token function">getDetailMessage</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
transaction<span class="token punctuation">.</span><span class="token function">setStatus</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">;</span>
exception <span class="token operator">=</span> ex<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
transaction<span class="token punctuation">.</span><span class="token function">complete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
m_configUtil<span class="token punctuation">.</span><span class="token function">getOnErrorRetryIntervalTimeUnit</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">sleep</span><span class="token punctuation">(</span>m_configUtil<span class="token punctuation">.</span><span class="token function">getOnErrorRetryInterval</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">//ignore</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ApolloConfigException</span><span class="token punctuation">(</span>
<span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"Get config services failed from %s"</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span><span class="token punctuation">,</span> exception<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div><footer class=post-footer><div class=post-eof></div></footer></article></div><div class=post-block><article class=post-content itemscope itemtype=http://schema.org/Article><link href=https://nicksxs.me/2022/09/11/Leetcode-1862-%E5%90%91%E4%B8%8B%E5%8F%96%E6%95%B4%E6%95%B0%E5%AF%B9%E5%92%8C-Sum-of-Floored-Pairs-Hard-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ itemprop=mainEntityOfPage><span hidden itemprop=author itemscope itemtype=http://schema.org/Person><meta content=/uploads/avatar.jpg itemprop=image><meta content=Nicksxs itemprop=name></span><span hidden itemprop=publisher itemscope itemtype=http://schema.org/Organization><meta content="Nicksxs's Blog" itemprop=name><meta content="learn from zero,技术博客,Nicksxs,史学森" itemprop=description></span><span hidden itemprop=post itemscope itemtype=http://schema.org/CreativeWork><meta content="undefined | Nicksxs's Blog" itemprop=name><meta itemprop=description></span><header class=post-header><h2 itemprop="name headline" class=post-title><a class=post-title-link href=/2022/09/11/Leetcode-1862-%E5%90%91%E4%B8%8B%E5%8F%96%E6%95%B4%E6%95%B0%E5%AF%B9%E5%92%8C-Sum-of-Floored-Pairs-Hard-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ itemprop=url>Leetcode 1862 向下取整数对和 ( Sum of Floored Pairs *Hard* ) 题解分析</a></h2><div class=post-meta-container><div class=post-meta><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-calendar"></i> </span><span class=post-meta-item-text>发表于</span> <time itemprop="dateCreated datePublished" title="创建时间:2022-09-11 22:28:00" datetime=2022-09-11T22:28:00+08:00>2022-09-11</time> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-folder"></i> </span><span class=post-meta-item-text>分类于</span> <span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/ itemprop=url rel=index><span itemprop=name>Java</span></a> </span><span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/leetcode/ itemprop=url rel=index><span itemprop=name>leetcode</span></a> </span></span><span class="post-meta-item leancloud_visitors" data-flag-title="Leetcode 1862 向下取整数对和 ( Sum of Floored Pairs *Hard* ) 题解分析" id=/2022/09/11/Leetcode-1862-%E5%90%91%E4%B8%8B%E5%8F%96%E6%95%B4%E6%95%B0%E5%AF%B9%E5%92%8C-Sum-of-Floored-Pairs-Hard-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ title=阅读次数><span class=post-meta-item-icon><i class="far fa-eye"></i> </span><span class=post-meta-item-text>阅读次数:</span> <span class=leancloud-visitors-count></span> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-comment"></i> </span><span class=post-meta-item-text>Disqus:</span> <a href=/2022/09/11/Leetcode-1862-%E5%90%91%E4%B8%8B%E5%8F%96%E6%95%B4%E6%95%B0%E5%AF%B9%E5%92%8C-Sum-of-Floored-Pairs-Hard-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2022/09/11/Leetcode-1862-向下取整数对和-Sum-of-Floored-Pairs-Hard-题解分析/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><h3 id=题目介绍><a class=headerlink href=#题目介绍 title=题目介绍></a>题目介绍</h3><p>Given an integer array <code>nums</code>, return the sum of <code>floor(nums[i] / nums[j])</code> for all pairs of indices <code>0 <= i, j < nums.length</code> in the array. Since the answer may be too large, return it modulo <code>10^9 + 7</code>.<p>The <code>floor()</code> function returns the integer part of the division.<p>对应中文<br>给你一个整数数组 <code>nums</code> ,请你返回所有下标对 <code>0 <= i, j < nums.length</code> 的 <code>floor(nums[i] / nums[j])</code> 结果之和。由于答案可能会很大,请你返回答案对<code>10^9 + 7</code> 取余 的结果。<p>函数 <code>floor()</code> 返回输入数字的整数部分。<h3 id=示例><a class=headerlink href=#示例 title=示例></a>示例</h3><h4 id=Example-1><a title="Example 1:" class=headerlink href=#Example-1></a>Example 1:</h4><blockquote><p><strong>Input:</strong> nums = [2,5,9]<br><strong>Output:</strong> 10<br><strong>Explanation:</strong><br>floor(2 / 5) = floor(2 / 9) = floor(5 / 9) = 0<br>floor(2 / 2) = floor(5 / 5) = floor(9 / 9) = 1<br>floor(5 / 2) = 2<br>floor(9 / 2) = 4<br>floor(9 / 5) = 1<br>We calculate the floor of the division for every pair of indices in the array then sum them up.</blockquote><h4 id=Example-2><a title="Example 2:" class=headerlink href=#Example-2></a>Example 2:</h4><blockquote><p><strong>Input:</strong> nums = [7,7,7,7,7,7,7]<br><strong>Output:</strong> 49</blockquote><h4 id=Constraints><a class=headerlink href=#Constraints title=Constraints:></a>Constraints:</h4><ul><li><code>1 <= nums.length <= 10^5</code><li><code>1 <= nums[i] <= 10^5</code></ul><h3 id=简析><a class=headerlink href=#简析 title=简析></a>简析</h3><p>这题不愧是 hard,要不是看了讨论区的一个大神的解答感觉从头做得想好久,<br>主要是两点,对于任何一个在里面的数,随便举个例子是 k,最简单的就是循环所有数对 k 除一下,<br>这样效率会很低,那么对于 k 有什么规律呢,就是对于所有小于 k 的数,往下取整都是 0,所以不用考虑,<br>对于所有大于 k 的数我们可以分成一个个的区间,[k,2k-1),[2k,3k-1),[3k,4k-1)……对于这些区间的<br>除了 k 往下取整,每个区间内的都是一样的,所以可以简化为对于任意一个 k,我只要知道与k 相同的有多少个,然后比 k 大的各个区间各有多少个数就可以了<h3 id=代码><a class=headerlink href=#代码 title=代码></a>代码</h3><pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">MAXE5</span> <span class="token operator">=</span> <span class="token number">100_000</span><span class="token punctuation">;</span>
<span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token constant">MODULUSE9</span> <span class="token operator">=</span> <span class="token number">1_000_000_000</span> <span class="token operator">+</span> <span class="token number">7</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">sumOfFlooredPairs</span><span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> nums<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span> counts <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token constant">MAXE5</span><span class="token operator">+</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> num <span class="token operator">:</span> nums<span class="token punctuation">)</span> <span class="token punctuation">{</span>
counts<span class="token punctuation">[</span>num<span class="token punctuation">]</span><span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 这里就是很巧妙的给后一个加上前一个的值,这样其实前后任意两者之差就是这中间的元素数量</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token constant">MAXE5</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
counts<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+=</span> counts<span class="token punctuation">[</span>i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">long</span> total <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><=</span> <span class="token constant">MAXE5</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> sum <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>counts<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">==</span> counts<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">continue</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i<span class="token operator">*</span>j <span class="token operator"><=</span> <span class="token constant">MAXE5</span><span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> min <span class="token operator">=</span> i <span class="token operator">*</span> j <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> upper <span class="token operator">=</span> i <span class="token operator">*</span> <span class="token punctuation">(</span>j <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token comment">// 在每一个区间内的数量,</span>
sum <span class="token operator">+=</span> <span class="token punctuation">(</span>counts<span class="token punctuation">[</span><span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>upper<span class="token punctuation">,</span> <span class="token constant">MAXE5</span><span class="token punctuation">)</span><span class="token punctuation">]</span> <span class="token operator">-</span> counts<span class="token punctuation">[</span>min<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token punctuation">(</span><span class="token keyword">long</span><span class="token punctuation">)</span>j<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 左边乘数的数量,即 i 位置的元素数量</span>
total <span class="token operator">=</span> <span class="token punctuation">(</span>total <span class="token operator">+</span> <span class="token punctuation">(</span>sum <span class="token operator">%</span> <span class="token constant">MODULUSE9</span> <span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token punctuation">(</span>counts<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">-</span> counts<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token constant">MODULUSE9</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>total<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>贴出来大神的解析,<a href=https://leetcode.com/problems/sum-of-floored-pairs/discuss/1210222/Java-O(n-log(n))-Straightforward-brute-force-with-explanation-76-ms rel=noopener target=_blank>解析</a><h3 id=结果><a class=headerlink href=#结果 title=结果></a>结果</h3><p><img data-src=https://img.nicksxs.com/uPic/U6MYqd.png></div><footer class=post-footer><div class=post-eof></div></footer></article></div><div class=post-block><article class=post-content itemscope itemtype=http://schema.org/Article><link href=https://nicksxs.me/2022/09/04/Apollo-%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%8E%AF%E5%A2%83/ itemprop=mainEntityOfPage><span hidden itemprop=author itemscope itemtype=http://schema.org/Person><meta content=/uploads/avatar.jpg itemprop=image><meta content=Nicksxs itemprop=name></span><span hidden itemprop=publisher itemscope itemtype=http://schema.org/Organization><meta content="Nicksxs's Blog" itemprop=name><meta content="learn from zero,技术博客,Nicksxs,史学森" itemprop=description></span><span hidden itemprop=post itemscope itemtype=http://schema.org/CreativeWork><meta content="undefined | Nicksxs's Blog" itemprop=name><meta itemprop=description></span><header class=post-header><h2 itemprop="name headline" class=post-title><a class=post-title-link href=/2022/09/04/Apollo-%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%8E%AF%E5%A2%83/ itemprop=url>Apollo 如何获取当前环境</a></h2><div class=post-meta-container><div class=post-meta><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-calendar"></i> </span><span class=post-meta-item-text>发表于</span> <time itemprop="dateCreated datePublished" title="创建时间:2022-09-04 21:08:27" datetime=2022-09-04T21:08:27+08:00>2022-09-04</time> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-folder"></i> </span><span class=post-meta-item-text>分类于</span> <span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/ itemprop=url rel=index><span itemprop=name>Java</span></a> </span></span><span class="post-meta-item leancloud_visitors" data-flag-title="Apollo 如何获取当前环境" id=/2022/09/04/Apollo-%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%8E%AF%E5%A2%83/ title=阅读次数><span class=post-meta-item-icon><i class="far fa-eye"></i> </span><span class=post-meta-item-text>阅读次数:</span> <span class=leancloud-visitors-count></span> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-comment"></i> </span><span class=post-meta-item-text>Disqus:</span> <a href=/2022/09/04/Apollo-%E5%A6%82%E4%BD%95%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E7%8E%AF%E5%A2%83/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2022/09/04/Apollo-如何获取当前环境/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>在用 <a href=https://github.com/apolloconfig/apollo rel=noopener target=_blank>Apollo</a> 作为配置中心的过程中才到过几个坑,这边记录下,因为运行 java 服务的启动参数一般比较固定,所以我们在一个新环境里运行的时候没有特意去检查,然后突然发现业务上有一些数据异常,排查之后才发现java 服务连接了测试环境的 apollo,而原因是因为环境变量传了<code>-Denv=fat</code>,而在我们的环境配置中 fat 就是代表测试环境, 其实应该是<code>-Denv=pro</code>,而 apollo 总共有这些环境<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">public</span> <span class="token keyword">enum</span> <span class="token class-name">Env</span><span class="token punctuation">{</span>
<span class="token constant">LOCAL</span><span class="token punctuation">,</span> <span class="token constant">DEV</span><span class="token punctuation">,</span> <span class="token constant">FWS</span><span class="token punctuation">,</span> <span class="token constant">FAT</span><span class="token punctuation">,</span> <span class="token constant">UAT</span><span class="token punctuation">,</span> <span class="token constant">LPT</span><span class="token punctuation">,</span> <span class="token constant">PRO</span><span class="token punctuation">,</span> <span class="token constant">TOOLS</span><span class="token punctuation">,</span> <span class="token constant">UNKNOWN</span><span class="token punctuation">;</span>
<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">Env</span> <span class="token function">fromString</span><span class="token punctuation">(</span><span class="token class-name">String</span> env<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Env</span> environment <span class="token operator">=</span> <span class="token class-name">EnvUtils</span><span class="token punctuation">.</span><span class="token function">transformEnv</span><span class="token punctuation">(</span>env<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Preconditions</span><span class="token punctuation">.</span><span class="token function">checkArgument</span><span class="token punctuation">(</span>environment <span class="token operator">!=</span> <span class="token constant">UNKNOWN</span><span class="token punctuation">,</span> <span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"Env %s is invalid"</span><span class="token punctuation">,</span> env<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> environment<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>而这些解释<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/**
* Here is the brief description for all the predefined environments:
* &LTul>
* &LTli>LOCAL: Local Development environment, assume you are working at the beach with no network access&LT/li>
* &LTli>DEV: Development environment&LT/li>
* &LTli>FWS: Feature Web Service Test environment&LT/li>
* &LTli>FAT: Feature Acceptance Test environment&LT/li>
* &LTli>UAT: User Acceptance Test environment&LT/li>
* &LTli>LPT: Load and Performance Test environment&LT/li>
* &LTli>PRO: Production environment&LT/li>
* &LTli>TOOLS: Tooling environment, a special area in production environment which allows
* access to test environment, e.g. Apollo Portal should be deployed in tools environment&LT/li>
* &LT/ul>
*/</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>那如果要在运行时知道 apollo 当前使用的环境可以用这个<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token class-name">Env</span> apolloEnv <span class="token operator">=</span> <span class="token class-name">ApolloInjector</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token class-name">ConfigUtil</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getApolloEnv</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden=true class=line-numbers-rows><span></span></span></code></pre><p>简单记录下。</div><footer class=post-footer><div class=post-eof></div></footer></article></div><div class=post-block><article class=post-content itemscope itemtype=http://schema.org/Article><link href=https://nicksxs.me/2022/08/23/Leetcode-885-%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5-III-Spiral-Matrix-III-Medium-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ itemprop=mainEntityOfPage><span hidden itemprop=author itemscope itemtype=http://schema.org/Person><meta content=/uploads/avatar.jpg itemprop=image><meta content=Nicksxs itemprop=name></span><span hidden itemprop=publisher itemscope itemtype=http://schema.org/Organization><meta content="Nicksxs's Blog" itemprop=name><meta content="learn from zero,技术博客,Nicksxs,史学森" itemprop=description></span><span hidden itemprop=post itemscope itemtype=http://schema.org/CreativeWork><meta content="undefined | Nicksxs's Blog" itemprop=name><meta itemprop=description></span><header class=post-header><h2 itemprop="name headline" class=post-title><a class=post-title-link href=/2022/08/23/Leetcode-885-%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5-III-Spiral-Matrix-III-Medium-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ itemprop=url>Leetcode 885 螺旋矩阵 III ( Spiral Matrix III *Medium* ) 题解分析</a></h2><div class=post-meta-container><div class=post-meta><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-calendar"></i> </span><span class=post-meta-item-text>发表于</span> <time itemprop="dateCreated datePublished" title="创建时间:2022-08-23 22:14:29" datetime=2022-08-23T22:14:29+08:00>2022-08-23</time> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-folder"></i> </span><span class=post-meta-item-text>分类于</span> <span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/ itemprop=url rel=index><span itemprop=name>Java</span></a> </span><span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/leetcode/ itemprop=url rel=index><span itemprop=name>leetcode</span></a> </span></span><span class="post-meta-item leancloud_visitors" data-flag-title="Leetcode 885 螺旋矩阵 III ( Spiral Matrix III *Medium* ) 题解分析" id=/2022/08/23/Leetcode-885-%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5-III-Spiral-Matrix-III-Medium-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ title=阅读次数><span class=post-meta-item-icon><i class="far fa-eye"></i> </span><span class=post-meta-item-text>阅读次数:</span> <span class=leancloud-visitors-count></span> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-comment"></i> </span><span class=post-meta-item-text>Disqus:</span> <a href=/2022/08/23/Leetcode-885-%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5-III-Spiral-Matrix-III-Medium-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2022/08/23/Leetcode-885-螺旋矩阵-III-Spiral-Matrix-III-Medium-题解分析/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><h3 id=题目介绍><a class=headerlink href=#题目介绍 title=题目介绍></a>题目介绍</h3><p>You start at the cell (rStart, cStart) of an rows x cols grid facing east. The northwest corner is at the first row and column in the grid, and the southeast corner is at the last row and column.<p>You will walk in a clockwise spiral shape to visit every position in this grid. Whenever you move outside the grid’s boundary, we continue our walk outside the grid (but may return to the grid boundary later.). Eventually, we reach all rows * cols spaces of the grid.<p>Return an array of coordinates representing the positions of the grid in the order you visited them.<h4 id=Example-1><a title="Example 1:" class=headerlink href=#Example-1></a>Example 1:</h4><blockquote><p><strong>Input:</strong> rows = 1, cols = 4, rStart = 0, cStart = 0<br><strong>Output:</strong> [[0,0],[0,1],[0,2],[0,3]]</blockquote><h4 id=Example-2><a title="Example 2:" class=headerlink href=#Example-2></a>Example 2:</h4><blockquote><p><strong>Input:</strong> rows = 5, cols = 6, rStart = 1, cStart = 4<br><strong>Output:</strong> [[1,4],[1,5],[2,5],[2,4],[2,3],[1,3],[0,3],[0,4],[0,5],[3,5],[3,4],[3,3],[3,2],[2,2],[1,2],[0,2],[4,5],[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,1],[0,1],[4,0],[3,0],[2,0],[1,0],[0,0]]</blockquote><p><strong>Constraints:</strong><ul><li><code>1 <= rows, cols <= 100</code><li><code>0 <= rStart < rows</code><li><code>0 <= cStart < cols</code></ul><h3 id=简析><a class=headerlink href=#简析 title=简析></a>简析</h3><p>这个题主要是要相同螺旋矩阵的转变方向的边界判断,已经相同步长会行进两次这个规律,写代码倒不复杂<h3 id=代码><a class=headerlink href=#代码 title=代码></a>代码</h3><pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">public</span> <span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token function">spiralMatrixIII</span><span class="token punctuation">(</span><span class="token keyword">int</span> rows<span class="token punctuation">,</span> <span class="token keyword">int</span> cols<span class="token punctuation">,</span> <span class="token keyword">int</span> rStart<span class="token punctuation">,</span> <span class="token keyword">int</span> cStart<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">int</span> size <span class="token operator">=</span> rows <span class="token operator">*</span> cols<span class="token punctuation">;</span>
<span class="token keyword">int</span> x <span class="token operator">=</span> rStart<span class="token punctuation">,</span> y <span class="token operator">=</span> cStart<span class="token punctuation">;</span>
<span class="token comment">// 返回的二维矩阵</span>
<span class="token keyword">int</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token punctuation">]</span> matrix <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">int</span><span class="token punctuation">[</span>size<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// 传入的参数就是入口第一个</span>
matrix<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> rStart<span class="token punctuation">;</span>
matrix<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> cStart<span class="token punctuation">;</span>
<span class="token comment">// 作为数量</span>
<span class="token keyword">int</span> z <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token comment">// 步进,1,1,2,2,3,3,4 ... 螺旋矩阵的增长</span>
<span class="token keyword">int</span> a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token comment">// 方向 1 表示右,2 表示下,3 表示左,4 表示上</span>
<span class="token keyword">int</span> dir <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>z <span class="token operator"><</span> size<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">2</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j<span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator"><</span> a<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 处理方向</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>dir <span class="token operator">%</span> <span class="token number">4</span> <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
y<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>dir <span class="token operator">%</span> <span class="token number">4</span> <span class="token operator">==</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
x<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>dir <span class="token operator">%</span> <span class="token number">4</span> <span class="token operator">==</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
y<span class="token operator">--</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
x<span class="token operator">--</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 如果在实际矩阵内</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>x <span class="token operator"><</span> rows <span class="token operator">&&</span> y <span class="token operator"><</span> cols <span class="token operator">&&</span> x <span class="token operator">>=</span> <span class="token number">0</span> <span class="token operator">&&</span> y <span class="token operator">>=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
matrix<span class="token punctuation">[</span>z<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> x<span class="token punctuation">;</span>
matrix<span class="token punctuation">[</span>z<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> y<span class="token punctuation">;</span>
z<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// 转变方向</span>
dir<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 步进++</span>
a<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> matrix<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id=结果><a class=headerlink href=#结果 title=结果></a>结果</h3><p><img data-src=https://img.nicksxs.com/uPic/2w6vbW.png></div><footer class=post-footer><div class=post-eof></div></footer></article></div><nav class=pagination><a class="extend prev" aria-label=上一页 href=/page/10/ rel=prev title=上一页><i class="fa fa-angle-left"></i></a><a class=page-number href=/>1</a><span class=space></span><a class=page-number href=/page/10/>10</a><span class="page-number current">11</span><a class=page-number href=/page/12/>12</a><span class=space></span><a class=page-number href=/page/46/>46</a><a class="extend next" aria-label=下一页 href=/page/12/ rel=next title=下一页><i class="fa fa-angle-right"></i></a></nav></div></main><footer class=footer><div class=footer-inner><div class=beian><a href=https://beian.miit.gov.cn/ rel=noopener target=_blank>浙ICP备16002580号-2 </a><img alt src=/uploads/beian.png><a href=http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=33010602011094 rel=noopener target=_blank>浙公网安备 33010602011094号</a></div><div class=copyright>© <span itemprop=copyrightYear>2023</span><span class=with-love><i class="fa fa-heart"></i> </span><span class=author itemprop=copyrightHolder>Nicksxs</span></div><div class=busuanzi-count><span class=post-meta-item id=busuanzi_container_site_uv><span class=post-meta-item-icon><i class="fa fa-user"></i> </span><span class=site-uv title=总访客量><span id=busuanzi_value_site_uv></span> </span></span><span class=post-meta-item id=busuanzi_container_site_pv><span class=post-meta-item-icon><i class="fa fa-eye"></i> </span><span class=site-pv title=总访问量><span id=busuanzi_value_site_pv></span></span></span></div></div></footer><div aria-label=返回顶部 class=back-to-top role=button><i class="fa fa-arrow-up fa-lg"></i><span>0%</span></div><a aria-label="Follow me on GitHub" title="Follow me on GitHub" class=github-corner href=https://github.com/nicksxs rel=noopener target=_blank><svg viewbox="0 0 250 250" aria-hidden=true height=80 width=80><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" style="transform-origin:130px 106px" class=octo-arm fill=currentColor></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" class=octo-body fill=currentColor></path></svg></a><noscript><div class=noscript-warning>Theme NexT works best with JavaScript enabled</div></noscript><script crossorigin=anonymous integrity=sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY= src=https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js></script><script crossorigin=anonymous integrity=sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU= src=https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js></script><script crossorigin=anonymous integrity=sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8= src=https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js></script><script crossorigin=anonymous integrity=sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc= src=https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js></script><script src=/js/comments.js></script><script src=/js/utils.js></script><script src=/js/motion.js></script><script src=/js/next-boot.js></script><script crossorigin=anonymous integrity=sha256-dyJcbGuYfdzNfifkHxYVd/rzeR6SLLcDFYEidcybldM= src=https://cdnjs.cloudflare.com/ajax/libs/algoliasearch/4.14.3/algoliasearch-lite.umd.js></script><script crossorigin=anonymous integrity=sha256-Nu8yqoXoRZEVYyZf4/eY1V4FsenbiCw85RY3gWjN3zQ= src=https://cdnjs.cloudflare.com/ajax/libs/instantsearch.js/4.49.2/instantsearch.production.min.js></script><script src=/js/third-party/search/algolia-search.js></script><script src=/js/third-party/fancybox.js></script><script async src=https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js></script><script class=next-config data-name=leancloud_visitors type=application/json>{"enable":true,"app_id":"ysza182Vghlqjdt7QiwGLLJy-gzGzoHsz","app_key":"s9GDqbn7gnGGkusf66YRVccw","server_url":"https://leancloud.cn","security":true}</script><script src=/js/third-party/statistics/lean-analytics.js></script><script crossorigin=anonymous integrity=sha256-yvJQOINiH9fWemHn0vCA5lsHWJaHs6/ZmO+1Ft04SvM= src=https://cdnjs.cloudflare.com/ajax/libs/quicklink/2.3.0/quicklink.umd.js></script><script class=next-config data-name=quicklink type=application/json>{"enable":false,"home":false,"archive":false,"delay":true,"timeout":3000,"priority":true,"url":"https://nicksxs.me/page/11/"}</script><script src=/js/third-party/quicklink.js></script><script class=next-config data-name=disqus type=application/json>{"enable":true,"shortname":"nicksxs","count":true,"i18n":{"disqus":"disqus"}}</script><script src=/js/third-party/comments/disqus.js></script>