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.
 
 

9 lines
182 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 7.1.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}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)}/*!
Theme: Default
Description: Original highlight.js style
Author: (c) Ivan Sagalaev <maniac@softwaremaniacs.org>
Maintainer: @highlightjs/core-team
Website: https://highlightjs.org/
License: see project LICENSE
Touched: 2021
*/pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{background:#f3f3f3;color:#444}.hljs-comment{color:#697070}.hljs-punctuation,.hljs-tag{color:#444a}.hljs-tag .hljs-attr,.hljs-tag .hljs-name{color:#444}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-operator,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#ab5656}.hljs-literal{color:#695}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta .hljs-string{color:#38a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}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}.code-container:hover .copy-btn,.highlight:hover .copy-btn{opacity:1}.code-container{position:relative}.copy-btn{color:#333;cursor:pointer;line-height:1.6;opacity:0;padding:2px 6px;position:absolute;transition:opacity .2s ease-in-out;background-color:#eee;background-image:linear-gradient(#fcfcfc,#eee);border:1px solid #d5d5d5;border-radius:3px;font-size:.8125em;right:4px;top:8px}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{overflow:auto;position:relative}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[class^=fa],.tabs-comment ul.nav-tabs li.tab a i[class^=fa]{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,visibility .2s ease-in-out;visibility:hidden}body:not(.site-nav-on) .site-nav .animated{animation:none}body.site-nav-on .site-nav{height:var(--scroll-height);visibility:unset}}.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 i[class^=fa]{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 i[class^=fa]{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 i[class^=fa]{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{font-size:.875em;height:0;margin:0;overflow:hidden;padding-left:0;pointer-events:none;transition:height .2s ease-in-out,visibility .2s ease-in-out;visibility:hidden}.sidebar-nav-active .sidebar-nav{height:calc(2em + 1px);pointer-events:unset;visibility:unset}.sidebar-nav li{border-bottom:1px solid transparent;color:var(--text-color);cursor:pointer;display:inline-block;transition:border-bottom-color .2s ease-in-out,color .2s ease-in-out}.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;transition-delay:0.2s}.sidebar-overview-active .sidebar-nav-overview:hover,.sidebar-toc-active .sidebar-nav-toc:hover{color:#fc6423}.sidebar-panel-container{align-items:start;display:grid;flex:1;overflow-x:hidden;overflow-y:auto;padding-top:0;transition:padding-top .2s ease-in-out}.sidebar-nav-active .sidebar-panel-container{padding-top:20px}.sidebar-panel{animation:.2s ease-in-out deactivate-sidebar-panel;grid-area:1/1;height:0;opacity:0;overflow:hidden;pointer-events:none;transform:translateY(0);transition:.2s ease-in-out;transition-property:opacity,transform,visibility;visibility:hidden}.sidebar-nav-active .sidebar-panel,.sidebar-overview-active .sidebar-panel.post-toc-wrap{transform:translateY(-20px)}.sidebar-overview-active:not(.sidebar-nav-active) .sidebar-panel.post-toc-wrap{transition-delay:0s,0.2s,0s}.sidebar-overview-active .sidebar-panel.site-overview-wrap,.sidebar-toc-active .sidebar-panel.post-toc-wrap{animation-name:activate-sidebar-panel;height:auto;opacity:1;pointer-events:unset;transform:translateY(0);transition-delay:0.2s,0.2s,0s;visibility:unset}.sidebar-panel.site-overview-wrap{display:flex;flex-direction:column;justify-content:center;gap:10px;justify-content:flex-start}@keyframes deactivate-sidebar-panel{from{height:var(--inactive-panel-height,0)}to{height:var(--active-panel-height,0)}}@keyframes activate-sidebar-panel{from{height:var(--inactive-panel-height,auto)}to{height:var(--active-panel-height,auto)}}.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 0 10px;text-align:left}.post-toc ol>:last-child{margin-bottom:5px}.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{--height:0;height:0;opacity:0;overflow:hidden;transition:.2s ease-in-out;visibility:hidden}.post-toc .nav .active>.nav-child{height:var(--height,auto);opacity:1;visibility:unset}.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;transition:left .2s ease-in-out,right .2s ease-in-out}.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 .fancybox+figcaption,.post-body img+figcaption{margin:-5px auto 15px!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::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 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{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;display:flex;flex-wrap:wrap;justify-content:center}.social-like a{border-bottom:none}.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.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.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,visibility .2s ease-in-out;visibility:hidden}body:not(.site-nav-on) .site-nav .animated{animation:none}body.site-nav-on .site-nav{height:var(--scroll-height);visibility:unset}}.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.5.0/css/all.min.css integrity=sha256-yIDrPSXHZdOZhAqiBP7CKzIwMQmRCJ8UeB8Jo17YC4o= 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/fancyapps-ui/5.0.28/fancybox/fancybox.css integrity=sha256-6cQIC71/iBIYXFK+0RHAvwmjwWzkWd+r7v/BX3/vZDc= rel=stylesheet><script class=next-config data-name=main type=application/json>{"hostname":"nicksxs.me","root":"/","images":"/images","scheme":"Pisces","darkmode":false,"version":"8.19.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"default"},"fold":{"enable":false,"height":500},"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/3/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/3/ rel=canonical><script class=next-config data-name=page type=application/json>{"sidebar":"","isHome":true,"isPost":false,"lang":"zh-CN","comments":"","permalink":"","path":"page/3/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,"measure_protocol_api_secret":null}</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-mirror"><a href=https://nicksxs.com/ rel=section target=_blank><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>263</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>163</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>300</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>71</span><li class=tag-list-item><a class=tag-list-link href=/tags/LLM/ rel=tag>LLM</a><span class=tag-list-count>2</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>22</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>13</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>5</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>4</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/http/ rel=tag>http</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>39</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>43</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>7</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>5</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>2</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%91%E6%9C%8D%E5%8A%A1%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/%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%8A%98%E8%85%BE/ 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>27</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/2024/02/11/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E7%AC%AC%E4%B8%80%E7%AF%87/ 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=/2024/02/11/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E7%AC%AC%E4%B8%80%E7%AF%87/ itemprop=url>Java 线程池系列-第一篇</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="创建时间:2024-02-11 19:39:05 / 修改时间:19:52:10" datetime=2024-02-11T19:39:05+08:00>2024-02-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><span class="post-meta-item leancloud_visitors" data-flag-title="Java 线程池系列-第一篇" id=/2024/02/11/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E7%AC%AC%E4%B8%80%E7%AF%87/ 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=/2024/02/11/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E7%AC%AC%E4%B8%80%E7%AF%87/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2024/02/11/Java-线程池系列-第一篇/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>这一篇我们继续聊线程池,一般线程池会介绍我们的参数,我先不一样一些<br>我们先来翻译一下<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br><span class=line>15</span><br><span class=line>16</span><br><span class=line>17</span><br><span class=line>18</span><br><span class=line>19</span><br><span class=line>20</span><br><span class=line>21</span><br><span class=line>22</span><br><span class=line>23</span><br><span class=line>24</span><br><span class=line>25</span><br><span class=line>26</span><br><span class=line>27</span><br><span class=line>28</span><br><span class=line>29</span><br><span class=line>30</span><br><span class=line>31</span><br><span class=line>32</span><br><span class=line>33</span><br><span class=line>34</span><br><span class=line>35</span><br><span class=line>36</span><br><span class=line>37</span><br><span class=line>38</span><br><span class=line>39</span><br><span class=line>40</span><br><span class=line>41</span><br><span class=line>42</span><br><span class=line>43</span><br><span class=line>44</span><br><span class=line>45</span><br><span class=line>46</span><br><span class=line>47</span><br><span class=line>48</span><br><span class=line>49</span><br><span class=line>50</span><br><span class=line>51</span><br><span class=line>52</span><br><span class=line>53</span><br><span class=line>54</span><br><span class=line>55</span><br><span class=line>56</span><br><span class=line>57</span><br><span class=line>58</span><br><span class=line>59</span><br><span class=line>60</span><br><span class=line>61</span><br><span class=line>62</span><br><span class=line>63</span><br><span class=line>64</span><br><span class=line>65</span><br><span class=line>66</span><br><span class=line>67</span><br><span class=line>68</span><br><span class=line>69</span><br><span class=line>70</span><br><span class=line>71</span><br><span class=line>72</span><br><span class=line>73</span><br><span class=line>74</span><br><span class=line>75</span><br><span class=line>76</span><br><span class=line>77</span><br><span class=line>78</span><br><span class=line>79</span><br><span class=line>80</span><br><span class=line>81</span><br><span class=line>82</span><br><span class=line>83</span><br><span class=line>84</span><br><span class=line>85</span><br><span class=line>86</span><br><span class=line>87</span><br><span class=line>88</span><br><span class=line>89</span><br><span class=line>90</span><br><span class=line>91</span><br><span class=line>92</span><br><span class=line>93</span><br><span class=line>94</span><br><span class=line>95</span><br></pre><td class=code><pre><span class=line> An {<span class=meta>@link</span> ExecutorService} that executes each submitted task using</span><br><span class=line> one of possibly several pooled threads, normally configured</span><br><span class=line> using {<span class=meta>@link</span> Executors} factory methods.</span><br><span class=line> <span class=comment>// executorService 使用一个线程池中的线程来执行每个提交的任务,经常使用 Executors 工厂方法</span></span><br><span class=line></span><br><span class=line> &LTp>Thread pools address two different problems: they usually</span><br><span class=line> provide improved performance when executing large numbers of</span><br><span class=line> asynchronous tasks, due to reduced per-task invocation overhead,</span><br><span class=line> and they provide a means of bounding and managing the resources,</span><br><span class=line> including threads, consumed when executing a collection of tasks.</span><br><span class=line> Each {<span class=meta>@code</span> ThreadPoolExecutor} also maintains some basic</span><br><span class=line> statistics, such as the number of completed tasks.</span><br><span class=line> <span class=comment>// 线程池解决两个不同的问题,通常是为了在提交大量异步任务时,通过减少每个任务的调度开销来提高性能</span></span><br><span class=line> <span class=comment>// 并且提供了一种管理和约束资源,包括线程消耗的方法,每个 ThreadPoolExecutor还会管理一些基础的统计信息</span></span><br><span class=line> <span class=comment>// 比如完成的任务数量</span></span><br><span class=line> </span><br><span class=line></span><br><span class=line> &LTp>To be useful across a wide range of contexts, <span class=built_in>this</span> <span class=keyword>class</span></span><br><span class=line> <span class="title class_">provides</span> many adjustable parameters and extensibility</span><br><span class=line> hooks. However, programmers are urged to use the more convenient</span><br><span class=line> {<span class=meta>@link</span> Executors} factory methods {<span class=meta>@link</span></span><br><span class=line> Executors#newCachedThreadPool} (unbounded thread pool, with</span><br><span class=line> automatic thread reclamation), {<span class=meta>@link</span> Executors#newFixedThreadPool}</span><br><span class=line> (fixed size thread pool) and {<span class=meta>@link</span></span><br><span class=line> Executors#newSingleThreadExecutor} (single background thread), that</span><br><span class=line> preconfigure settings <span class=keyword>for</span> the most common usage</span><br><span class=line> scenarios. Otherwise, use the following guide when manually</span><br><span class=line> configuring and tuning <span class=built_in>this</span> class:</span><br><span class=line> <span class=comment>// 为了在各种情况下都能派上用场,该类提供了许多可调整的参数和扩展钩子。不过,我们建议程序员使用更方便的 Executors 工厂方法 Executors.</span></span><br><span class=line> <span class=comment>// newCachedThreadPool(无限制线程池,可自动回收线程)、Executors.newFixedThreadPool(固定大小线程池)和 Executors.</span></span><br><span class=line> <span class=comment>// newSingleThreadExecutor(单后台线程),这些方法可为最常见的使用场景预先配置设置。否则,在手动配置和调整该类时,请使用以下指南:</span></span><br><span class=line></span><br><span class=line> Core and maximum pool sizes</span><br><span class=line> <span class=comment>// 核心和最大线程池大小</span></span><br><span class=line> A ThreadPoolExecutor will automatically adjust the pool <span class="title function_">size</span> <span class=params>(see getPoolSize)</span> according to the bounds set by <span class="title function_">corePoolSize</span> <span class=params>(see getCorePoolSize)</span> and <span class="title function_">maximumPoolSize</span> <span class=params>(see getMaximumPoolSize)</span>. When a <span class=keyword>new</span> <span class="title class_">task</span> is submitted in method <span class="title function_">execute</span><span class=params>(Runnable)</span>, and fewer than corePoolSize threads are running, a <span class=keyword>new</span> <span class="title class_">thread</span> is created to handle the request, even <span class=keyword>if</span> other worker threads are idle. If there are more than corePoolSize but less than maximumPoolSize threads running, a <span class=keyword>new</span> <span class="title class_">thread</span> will be created only <span class=keyword>if</span> the queue is full. By setting corePoolSize and maximumPoolSize the same, you create a fixed-size thread pool. By setting maximumPoolSize to an essentially unbounded value such as Integer.MAX_VALUE, you allow the pool to accommodate an arbitrary number of concurrent tasks. Most typically, core and maximum pool sizes are set only upon construction, but they may also be changed dynamically using setCorePoolSize and setMaximumPoolSize.</span><br><span class=line> <span class=comment>// ThreadPoolExecutor 会根据 corePoolSize(参见 getCorePoolSize)和 maximumPoolSize(参见 getMaximumPoolSize)设置的界限自动调整池大小(参见 getPoolSize)。在方法 execute(Runnable) 中提交新任务时,如果运行的线程少于 corePoolSize,即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求。如果运行的线程多于 corePoolSize 但少于 maximumPoolSize,则只有在队列已满时才会创建新线程。如果将 corePoolSize 和 maximumPoolSize 设置为相同,就可以创建一个固定大小的线程池。如果将 maximumPoolSize 设置为 Integer.MAX_VALUE 等基本无限制的值,就可以让池容纳任意数量的并发任务。通常,核心和最大线程池大小只在构建时设置,但也可以使用 setCorePoolSize 和 setMaximumPoolSize 动态更改。</span></span><br><span class=line></span><br><span class=line>On-demand construction</span><br><span class=line><span class=comment>// 按需构建</span></span><br><span class=line> By <span class=keyword>default</span>, even core threads are initially created and started only when <span class=keyword>new</span> <span class="title class_">tasks</span> arrive, but <span class=built_in>this</span> can be overridden dynamically using method prestartCoreThread or prestartAllCoreThreads. You probably want to prestart threads <span class=keyword>if</span> you construct the pool with a non-empty queue.</span><br><span class=line> <span class=comment>// 默认情况下,即使是核心线程也是只有当新任务到来时才会初始创建和启动,但这可以使用方法 prestartCoreThread 或 prestartAllCoreThreads 进行动态重载。如果使用非空队列构建线程池,则可能需要预启动线程。</span></span><br><span class=line>Creating <span class=keyword>new</span> <span class="title class_">threads</span></span><br><span class=line><span class=comment>// 创建新线程</span></span><br><span class=line> <span class=comment>/** New threads are created using a ThreadFactory. If not otherwise specified, a Executors.defaultThreadFactory is used, that creates threads to all be in the same ThreadGroup and with the same NORM_PRIORITY priority and non-daemon status. By supplying a different ThreadFactory, you can alter the thread's name, thread group, priority, daemon status, etc. If a ThreadFactory fails to create a thread when asked by returning null from newThread, the executor will continue, but might not be able to execute any tasks. Threads should possess the "modifyThread" RuntimePermission. If worker threads or other threads using the pool do not possess this permission, service may be degraded: configuration changes may not take effect in a timely manner, and a shutdown pool may remain in a state in which termination is possible but not completed. */</span></span><br><span class=line> <span class=comment>// 新线程是使用线程工厂(ThreadFactory)创建的。如果未另行指定,将使用 Executors.defaultThreadFactory 创建线程,创建的线程将全部位于同一线程组,并具有相同的 NORM_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以更改线程的名称、线程组、优先级、守护进程状态等。如果线程工厂无法按要求创建线程,从 newThread 返回空值,执行器将继续运行,但可能无法执行任何任务。线程应拥有 "modifyThread "运行时权限。如果工作线程或使用池的其他线程不具备此权限,服务可能会降级:配置更改可能无法及时生效,关闭的池可能会一直处于可以终止但无法完成的状态。</span></span><br><span class=line>Keep-alive times</span><br><span class=line><span class=comment>// 保活时间</span></span><br><span class=line> If the pool currently has more than corePoolSize threads, excess threads will be terminated <span class=keyword>if</span> they have been idle <span class=keyword>for</span> more than the <span class="title function_">keepAliveTime</span> <span class=params>(see getKeepAliveTime(TimeUnit)</span>). This provides a means of reducing resource consumption when the pool is not being actively used. If the pool becomes more active later, <span class=keyword>new</span> <span class="title class_">threads</span> will be constructed. This parameter can also be changed dynamically using method <span class="title function_">setKeepAliveTime</span><span class=params>(<span class=type>long</span>, TimeUnit)</span>. Using a value of Long.MAX_VALUE TimeUnit.NANOSECONDS effectively disables idle threads from ever terminating prior to shut down. By <span class=keyword>default</span>, the keep-alive policy applies only when there are more than corePoolSize threads. But method <span class="title function_">allowCoreThreadTimeOut</span><span class=params>(<span class=type>boolean</span>)</span> can be used to apply <span class=built_in>this</span> time-out policy to core threads as well, so <span class=type>long</span> as the keepAliveTime value is non-zero.</span><br><span class=line> <span class=comment>// 如果当前池中的线程数超过 corePoolSize,多余的线程在闲置时间超过 keepAliveTime(请参阅 getKeepAliveTime(TimeUnit))时将被终止。这提供了一种在线程池未被频繁使用时减少资源消耗的方法。如果以后池变得更加活跃,就会构建新线程。也可以使用方法 setKeepAliveTime(long, TimeUnit) 动态更改该参数。使用 Long.MAX_VALUE TimeUnit.NANOSECONDS 值可有效禁止闲置线程在关闭前终止。默认情况下,只有当线程数超过 corePoolSize 时,才会采用保持连接策略。但只要 keepAliveTime 值不为零,就可以使用方法 allowCoreThreadTimeOut(boolean) 将超时策略也应用到核心线程。</span></span><br><span class=line>Queuing</span><br><span class=line><span class=comment>// 队列</span></span><br><span class=line> Any BlockingQueue may be used to transfer and hold submitted tasks. The use of <span class=built_in>this</span> queue interacts with pool sizing:</span><br><span class=line> <span class=comment>// 任何阻塞队列(BlockingQueue)都可用于传输和保留已提交的任务。该队列的使用与线程池大小有关:</span></span><br><span class=line> If fewer than corePoolSize threads are running, the Executor always prefers adding a <span class=keyword>new</span> <span class="title class_">thread</span> rather than queuing.</span><br><span class=line> <span class=comment>// 如果运行的线程少于 corePoolSize,执行器总是倾向于添加新线程而不是队列。</span></span><br><span class=line> If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a <span class=keyword>new</span> <span class="title class_">thread</span>.</span><br><span class=line> <span class=comment>// 如果运行的线程数大于或等于 corePoolSize,执行器总是倾向于将请求排队,而不是添加新线程。</span></span><br><span class=line> If a request cannot be queued, a <span class=keyword>new</span> <span class="title class_">thread</span> is created unless <span class=built_in>this</span> would exceed maximumPoolSize, in which <span class=keyword>case</span>, the task will be rejected.</span><br><span class=line> <span class=comment>// 如果请求无法进队列,执行器会创建一个新线程,除非这样做会超过最大线程池大小(maximumPoolSize),在这种情况下,任务会被拒绝。</span></span><br><span class=line> There are three general strategies <span class=keyword>for</span> queuing:</span><br><span class=line> <span class=comment>// 入队一般有三种策略:</span></span><br><span class=line> Direct handoffs. A good <span class=keyword>default</span> choice <span class=keyword>for</span> a work queue is a SynchronousQueue that hands off tasks to threads without otherwise holding them. Here, an attempt to queue a task will fail <span class=keyword>if</span> no threads are immediately available to run it, so a <span class=keyword>new</span> <span class="title class_">thread</span> will be constructed. This policy avoids lockups when handling sets of requests that might have internal dependencies. Direct handoffs generally require unbounded maximumPoolSizes to avoid rejection of <span class=keyword>new</span> <span class="title class_">submitted</span> tasks. This in turn admits the possibility of unbounded thread growth when commands <span class=keyword>continue</span> to arrive on average faster than they can be processed.</span><br><span class=line> <span class=comment>// 直接交接。工作队列的一个很好的默认选择是同步队列(SynchronousQueue),它可以将任务移交给线程,而不会以其他方式保留任务。在这里,如果没有线程可立即运行任务,则队列任务的尝试将失败,因此会构建一个新的线程。在处理可能存在内部依赖关系的请求集时,这种策略可以避免死锁。直接交接通常需要无限制的最大线程池大小,以避免新提交的任务被拒绝。反过来,当命令的平均到达速度超过其处理速度时,就有可能导致线程无限制增长。</span></span><br><span class=line> <span class=comment>/** Unbounded queues. Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity) will cause new tasks to wait in the queue when all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.) This may be appropriate when each task is completely independent of others, so tasks cannot affect each others execution; for example, in a web page server. While this style of queuing can be useful in smoothing out transient bursts of requests, it admits the possibility of unbounded work queue growth when commands continue to arrive on average faster than they can be processed. */</span></span><br><span class=line> <span class=comment>// 无界队列。使用无界队列(例如没有预定义容量的 LinkedBlockingQueue)会导致新任务在所有 corePoolSize 线程都繁忙时在队列中等待。因此,创建的线程不会超过 corePoolSize。(当每个任务都完全独立于其他任务,因此任务之间不会相互影响执行时,例如在网页服务器中,这种方式可能比较合适。虽然这种队列方式在平滑瞬时突发请求方面很有用,但当命令的平均到达速度持续超过其处理速度时,就会导致工作队列无限制地增长。</span></span><br><span class=line> Bounded queues. A bounded <span class="title function_">queue</span> <span class=params>(<span class=keyword>for</span> example, an ArrayBlockingQueue)</span> helps prevent resource exhaustion when used with finite maximumPoolSizes, but can be more difficult to tune and control. Queue sizes and maximum pool sizes may be traded off <span class=keyword>for</span> each other: Using large queues and small pools minimizes CPU usage, OS resources, and context-switching overhead, but can lead to artificially low throughput. If tasks frequently <span class="title function_">block</span> <span class=params>(<span class=keyword>for</span> example <span class=keyword>if</span> they are I/O bound)</span>, a system may be able to schedule time <span class=keyword>for</span> more threads than you otherwise allow. Use of small queues generally <span class=keyword>requires</span> larger pool sizes, which keeps CPUs busier but may encounter unacceptable scheduling overhead, which also decreases throughput.</span><br><span class=line> <span class=comment>// 有界队列 有界队列(例如 ArrayBlockingQueue)与有限的最大线程池大小一起使用时,有助于防止资源耗尽,但可能更难调整和控制。队列大小和最大池大小可以相互权衡: 使用大队列和小池可以最大限度地减少 CPU 占用率、操作系统资源和上下文切换开销,但会导致人为的低吞吐量。如果任务经常出现阻塞(例如,如果任务受 I/O 约束),系统可能会为更多线程安排时间,而不考虑其他因素。使用小队列通常需要更大的池规模,这将使 CPU 更繁忙,但可能会遇到无法接受的调度开销,这也会降低吞吐量。</span></span><br><span class=line>Rejected tasks</span><br><span class=line><span class=comment>// 被拒绝的任务</span></span><br><span class=line> New tasks submitted in method <span class="title function_">execute</span><span class=params>(Runnable)</span> will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds <span class=keyword>for</span> both maximum threads and work queue capacity, and is saturated. In either <span class=keyword>case</span>, the execute method invokes the RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor) method of its RejectedExecutionHandler. Four predefined handler policies are provided:</span><br><span class=line> <span class=comment>// 如果执行器已关闭,或者执行器使用了最大线程数和工作队列容量的有限界限,并已达到饱和,那么在 execute(Runnable) 方法中提交的新任务将被拒绝。在这两种情况下,execute 方法都会调用其 RejectedExecutionHandler 的 RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor) 方法。提供了四种预定义的处理程序策略:</span></span><br><span class=line> In the <span class=keyword>default</span> ThreadPoolExecutor.AbortPolicy, the handler <span class=keyword>throws</span> a runtime RejectedExecutionException upon rejection.</span><br><span class=line> <span class=comment>// 在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序会在拒绝时抛出运行时 RejectedExecutionException。</span></span><br><span class=line> In ThreadPoolExecutor.CallerRunsPolicy, the thread that invokes execute itself runs the task. This provides a simple feedback control mechanism that will slow down the rate that <span class=keyword>new</span> <span class="title class_">tasks</span> are submitted.</span><br><span class=line> <span class=comment>// 在 ThreadPoolExecutor.CallerRunsPolicy 中,调用执行本身的线程会运行任务。这提供了一个简单的反馈控制机制,可减慢提交新任务的速度。</span></span><br><span class=line> In ThreadPoolExecutor.DiscardPolicy, a task that cannot be executed is simply dropped.</span><br><span class=line> <span class=comment>// 在 ThreadPoolExecutor.DiscardPolicy 中,无法执行的任务会被直接丢弃。</span></span><br><span class=line> In ThreadPoolExecutor.DiscardOldestPolicy, <span class=keyword>if</span> the executor is not shut down, the task at the head of the work queue is dropped, and then execution is <span class="title function_">retried</span> <span class=params>(which can fail again, causing <span class=built_in>this</span> to be repeated.)</span></span><br><span class=line> <span class=comment>// 在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行器没有关闭,工作队列头部的任务就会被丢弃,然后重新执行(可能会再次失败,导致重复执行)。</span></span><br><span class=line> It is possible to define and use other kinds of RejectedExecutionHandler classes. Doing so <span class=keyword>requires</span> some care especially when policies are designed to work only under particular capacity or queuing policies.</span><br><span class=line> <span class=comment>// 我们还可以定义和使用其他类型的 RejectedExecutionHandler 类。这样做需要小心谨慎,尤其是当策略设计为仅在特定容量或队列策略下运行时。</span></span><br><span class=line>Hook methods</span><br><span class=line><span class=comment>// 钩子方法</span></span><br><span class=line> This <span class=keyword>class</span> <span class="title class_">provides</span> <span class=keyword>protected</span> overridable <span class="title function_">beforeExecute</span><span class=params>(Thread, Runnable)</span> and <span class="title function_">afterExecute</span><span class=params>(Runnable, Throwable)</span> methods that are called before and after execution of each task. These can be used to manipulate the execution environment; <span class=keyword>for</span> example, reinitializing ThreadLocals, gathering statistics, or adding log entries. Additionally, method terminated can be overridden to perform any special processing that needs to be done once the Executor has fully terminated.</span><br><span class=line> <span class=comment>// 该类提供 protected 的可重载 beforeExecute(Thread, Runnable) 和 afterExecute(Runnable, Throwable) 方法,可在每个任务执行前后调用。这些方法可用于操纵执行环境,例如,重新初始化线程位置、收集统计数据或添加日志条目。此外,还可以重写终止方法,以便在执行器完全终止后执行任何需要进行的特殊处理。(一些动态线程池技术就用到了这两个方法)</span></span><br><span class=line> If hook or callback methods <span class=keyword>throw</span> exceptions, internal worker threads may in turn fail and abruptly terminate.</span><br><span class=line> <span class=comment>// 如果钩子或回调方法抛出异常,内部工作线程可能会失败并突然终止。</span></span><br><span class=line>Queue maintenance</span><br><span class=line><span class=comment>// 队列维护</span></span><br><span class=line> Method <span class="title function_">getQueue</span><span class=params>()</span> allows access to the work queue <span class=keyword>for</span> purposes of monitoring and debugging. Use of <span class=built_in>this</span> method <span class=keyword>for</span> any other purpose is strongly discouraged. Two supplied methods, remove(Runnable) and purge are available to assist in storage reclamation when large numbers of queued tasks become cancelled.</span><br><span class=line> <span class=comment>// 方法 getQueue() 允许访问工作队列,以便进行监控和调试。强烈建议不要将此方法用于任何其他目的。当大量队列任务被取消时,可使用 remove(Runnable) 和 purge 这两个提供的方法来帮助回收存储空间。(不建议直接将获取到的队列进行修改操作)</span></span><br><span class=line>Finalization</span><br><span class=line><span class=comment>// 终止</span></span><br><span class=line> A pool that is no longer referenced in a program AND has no remaining threads will be shutdown automatically. If you would like to ensure that unreferenced pools are reclaimed even <span class=keyword>if</span> users forget to call shutdown, then you must arrange that unused threads eventually die, by setting appropriate keep-alive times, using a lower bound of zero core threads and/or setting <span class="title function_">allowCoreThreadTimeOut</span><span class=params>(<span class=type>boolean</span>)</span>.</span><br><span class=line> <span class=comment>// 程序中不再引用且没有剩余线程的池将自动关闭。如果要确保即使用户忘记调用 shutdown 也能回收未引用的池,则必须通过设置适当的保持连接时间、使用零核心线程下限和/或设置 allowCoreThreadTimeOut(boolean) 来使得未使用的线程最终被停止。</span></span><br></pre></table></figure><p>通过前面的简单翻译我们就能大致略窥得线程池配置全貌,继续看一个构造方法<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class="title function_">ThreadPoolExecutor</span><span class=params>(<span class=type>int</span> corePoolSize,</span></span><br><span class=line><span class=params> <span class=type>int</span> maximumPoolSize,</span></span><br><span class=line><span class=params> <span class=type>long</span> keepAliveTime,</span></span><br><span class=line><span class=params> TimeUnit unit,</span></span><br><span class=line><span class=params> BlockingQueue&LTRunnable> workQueue)</span> {</span><br><span class=line> <span class=built_in>this</span>(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,</span><br><span class=line> Executors.defaultThreadFactory(), defaultHandler);</span><br><span class=line>}</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>RejectedExecutionHandler</span> <span class=variable>defaultHandler</span> <span class=operator>=</span></span><br><span class=line> <span class=keyword>new</span> <span class="title class_">AbortPolicy</span>();</span><br></pre></table></figure><p>这个构造方法就主要配置了 <code>corePoolSize</code> 核心线程数,<code>maximumPoolSize</code> 最大线程数, <code>keepAliveTime</code> 线程保活时间,<code>unit</code> 时间单位,<code>workQueue</code> 工作队列,而传入后可以看到使用了默认的线程工厂和默认的拒绝处理器<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br><span class=line>15</span><br><span class=line>16</span><br><span class=line>17</span><br><span class=line>18</span><br><span class=line>19</span><br><span class=line>20</span><br><span class=line>21</span><br><span class=line>22</span><br><span class=line>23</span><br><span class=line>24</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class="title function_">ThreadPoolExecutor</span><span class=params>(<span class=type>int</span> corePoolSize,</span></span><br><span class=line><span class=params> <span class=type>int</span> maximumPoolSize,</span></span><br><span class=line><span class=params> <span class=type>long</span> keepAliveTime,</span></span><br><span class=line><span class=params> TimeUnit unit,</span></span><br><span class=line><span class=params> BlockingQueue&LTRunnable> workQueue,</span></span><br><span class=line><span class=params> ThreadFactory threadFactory,</span></span><br><span class=line><span class=params> RejectedExecutionHandler handler)</span> {</span><br><span class=line> <span class=keyword>if</span> (corePoolSize < <span class=number>0</span> ||</span><br><span class=line> maximumPoolSize <= <span class=number>0</span> ||</span><br><span class=line> maximumPoolSize < corePoolSize ||</span><br><span class=line> keepAliveTime < <span class=number>0</span>)</span><br><span class=line> <span class=keyword>throw</span> <span class=keyword>new</span> <span class="title class_">IllegalArgumentException</span>();</span><br><span class=line> <span class=keyword>if</span> (workQueue == <span class=literal>null</span> || threadFactory == <span class=literal>null</span> || handler == <span class=literal>null</span>)</span><br><span class=line> <span class=keyword>throw</span> <span class=keyword>new</span> <span class="title class_">NullPointerException</span>();</span><br><span class=line> <span class=built_in>this</span>.acc = System.getSecurityManager() == <span class=literal>null</span> ?</span><br><span class=line> <span class=literal>null</span> :</span><br><span class=line> AccessController.getContext();</span><br><span class=line> <span class=built_in>this</span>.corePoolSize = corePoolSize;</span><br><span class=line> <span class=built_in>this</span>.maximumPoolSize = maximumPoolSize;</span><br><span class=line> <span class=built_in>this</span>.workQueue = workQueue;</span><br><span class=line> <span class=built_in>this</span>.keepAliveTime = unit.toNanos(keepAliveTime);</span><br><span class=line> <span class=built_in>this</span>.threadFactory = threadFactory;</span><br><span class=line> <span class=built_in>this</span>.handler = handler;</span><br><span class=line>}</span><br></pre></table></figure><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/2024/02/04/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E5%87%86%E5%A4%87%E7%AF%87/ 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=/2024/02/04/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E5%87%86%E5%A4%87%E7%AF%87/ itemprop=url>Java 线程池系列-准备篇</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="创建时间:2024-02-04 23:10:20" datetime=2024-02-04T23:10:20+08:00>2024-02-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="Java 线程池系列-准备篇" id=/2024/02/04/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E5%87%86%E5%A4%87%E7%AF%87/ 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=/2024/02/04/Java-%E7%BA%BF%E7%A8%8B%E6%B1%A0%E7%B3%BB%E5%88%97-%E5%87%86%E5%A4%87%E7%AF%87/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2024/02/04/Java-线程池系列-准备篇/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>Java 线程池是 Java 并发体系里的重要组成部分,不过说起线程池一般都是几个参数,以及参数的含义和逻辑,为了更适合刚开始学习的同学或者说有一些会对这么个习惯性的概括讲法有点疑惑的,我们就从零开始,从最基础的开始看起,先来看下里面用来判断线程池状态和线程数量的部分<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br><span class=line>15</span><br></pre><td class=code><pre><span class=line><span class=keyword>private</span> <span class=keyword>final</span> <span class=type>AtomicInteger</span> <span class=variable>ctl</span> <span class=operator>=</span> <span class=keyword>new</span> <span class="title class_">AtomicInteger</span>(ctlOf(RUNNING, <span class=number>0</span>));</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>COUNT_BITS</span> <span class=operator>=</span> Integer.SIZE - <span class=number>3</span>;</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>CAPACITY</span> <span class=operator>=</span> (<span class=number>1</span> << COUNT_BITS) - <span class=number>1</span>;</span><br><span class=line></span><br><span class=line><span class=comment>// runState is stored in the high-order bits</span></span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>RUNNING</span> <span class=operator>=</span> -<span class=number>1</span> << COUNT_BITS;</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>SHUTDOWN</span> <span class=operator>=</span> <span class=number>0</span> << COUNT_BITS;</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>STOP</span> <span class=operator>=</span> <span class=number>1</span> << COUNT_BITS;</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>TIDYING</span> <span class=operator>=</span> <span class=number>2</span> << COUNT_BITS;</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>TERMINATED</span> <span class=operator>=</span> <span class=number>3</span> << COUNT_BITS;</span><br><span class=line></span><br><span class=line><span class=comment>// Packing and unpacking ctl</span></span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=type>int</span> <span class="title function_">runStateOf</span><span class=params>(<span class=type>int</span> c)</span> { <span class=keyword>return</span> c & ~CAPACITY; }</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=type>int</span> <span class="title function_">workerCountOf</span><span class=params>(<span class=type>int</span> c)</span> { <span class=keyword>return</span> c & CAPACITY; }</span><br><span class=line><span class=keyword>private</span> <span class=keyword>static</span> <span class=type>int</span> <span class="title function_">ctlOf</span><span class=params>(<span class=type>int</span> rs, <span class=type>int</span> wc)</span> { <span class=keyword>return</span> rs | wc; }</span><br></pre></table></figure><p>这里我们先看下 <code>COUNT_BITS</code> 它是 <code>Integer.SIZE - 3</code><code>Integer.SIZE</code> 这个是 32,也就是代表了 Java 用了四个 <code>Byte</code> 来存一个 <code>Integer</code>, 那么 <code>COUNT_BITS</code> 就是 29,<br>这个 29 是用了干嘛的呢,逐步往下看,为什么先介绍 <code>COUNT_BITS</code>,因为第一行的 <code>ctl</code> 的值是通过 <code>ctlOf(RUNNING, 0)</code> 算出来的,而 <code>RUNNING</code> 又是通过等于 <code>-1</code> 左移 <code>COUNT_BITS</code> 位来得到,移动 29 位后,还剩下三位,而这三位只需要表示后面五种状态,其中只有 <code>RUNNING</code> 是负值,这样就巧妙的只利用了 ctl 的前三位来存储线程池的状态而后面的 29 位就是用来存储线程数量的,具体怎么取呢,我们在来看下 <code>CAPACITY</code> 它是 <code>(1 << COUNT_BITS) - 1</code> 把 1 左移 29 位后减 1,也就是 536870911,这里再补充下,左移一位就等于是乘以 2,左移 29 位就是乘以 2 的 29 次,减了 1 就是 29 位能存的最大值,代表线程池最大的线程容量,用二进制来表示就是 32 位长度的int,前三位是 0,后 29 位是 1,代表了线程池的容量,那么 <code>runStateOf</code><code>workerCountOf</code> 的理解就很简单了,<br><code>runStateOf</code> 是 c 跟 CAPACITY 取反之后的值做”与”操作,<code>CAPACITY</code> 取反就变成了前三位是 1,后面的二十九位是 0,而对于”与”操作,后面的二十九位无论是什么都会被忽略,也就是取了前三位的值<br><code>workerCountOf</code> 正好相反,直接跟 <code>CAPACITY</code> 做 “与” 操作,也就是取后二十九位的值<br><code>ctlOf</code> 就是直接对 <code>rs</code><code>wc</code> 做了 “或” 操作<br>而前面也提到了只有 <code>RUNNING</code> 是负数,那么就可以直接做大小比较来判断线程池状态<br>这个可能对很多同学来说是非常简单的,但是对于一部分同学来说就是个拦路虎,希望能对这部分同学有所帮助。</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/2024/01/28/Leetcode-572-Subtree-of-Another-Tree-%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=/2024/01/28/Leetcode-572-Subtree-of-Another-Tree-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ itemprop=url>Leetcode 572 Subtree of Another Tree 题解分析</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="创建时间:2024-01-28 21:17:42" datetime=2024-01-28T21:17:42+08:00>2024-01-28</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 572 Subtree of Another Tree 题解分析" id=/2024/01/28/Leetcode-572-Subtree-of-Another-Tree-%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=/2024/01/28/Leetcode-572-Subtree-of-Another-Tree-%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=2024/01/28/Leetcode-572-Subtree-of-Another-Tree-题解分析/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><h2 id=题目介绍><a class=headerlink href=#题目介绍 title=题目介绍></a>题目介绍</h2><p>Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and false otherwise.<p>A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node’s descendants. The tree tree could also be considered as a subtree of itself.<h2 id=示例-1><a title="示例 1" class=headerlink href=#示例-1></a>示例 1</h2><p><img data-src=https://img.nicksxs.com/blog/3JTlNY.png><blockquote><p>Input: root = [3,4,5,1,2], subRoot = [4,1,2]<br>Output: true</blockquote><h2 id=示例-2><a title="示例 2" class=headerlink href=#示例-2></a>示例 2</h2><p><img data-src=https://img.nicksxs.com/blog/hnatjE.png><blockquote><p>Input: root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]<br>Output: false</blockquote><h2 id=解析><a class=headerlink href=#解析 title=解析></a>解析</h2><p>需要判断subRoot 为根节点的这棵树是不是 root 为根节点的这个树的子树,题应该不是特别难理解,只是需要注意,这里是子树,而不是一个子结构,也就是示例 2 的判断结果是 false,因为左边子树还有个 0,只能认为是左边的一部分,但不是子树,思路分析也不难,就是递归去判断,只不过是两种维度,第一种就是找到子树的根节点,也就是在 root 树找到 subRoot 的根节点相同的节点,这个就会用到递归,如果找到了一个,就开始递归的对比所有子节点,必须完全一样<h2 id=代码><a class=headerlink href=#代码 title=代码></a>代码</h2><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br><span class=line>15</span><br><span class=line>16</span><br><span class=line>17</span><br><span class=line>18</span><br><span class=line>19</span><br><span class=line>20</span><br><span class=line>21</span><br><span class=line>22</span><br><span class=line>23</span><br><span class=line>24</span><br><span class=line>25</span><br><span class=line>26</span><br><span class=line>27</span><br><span class=line>28</span><br><span class=line>29</span><br><span class=line>30</span><br><span class=line>31</span><br><span class=line>32</span><br><span class=line>33</span><br><span class=line>34</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class=type>boolean</span> <span class="title function_">isSubtree</span><span class=params>(TreeNode root, TreeNode subRoot)</span> {</span><br><span class=line> <span class=keyword>if</span> (subRoot == <span class=literal>null</span> || root == <span class=literal>null</span>) {</span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br><span class=line> <span class=keyword>if</span> (root.val == subRoot.val) {</span><br><span class=line> <span class=comment>// 如果 root 节点跟 subRoot 节点相同,就开始递归对比所有的子节点</span></span><br><span class=line> <span class=keyword>if</span> (isSameTree(root.left, subRoot.left) && isSameTree(root.right, subRoot.right)) {</span><br><span class=line> <span class=keyword>return</span> <span class=literal>true</span>;</span><br><span class=line> }</span><br><span class=line> }</span><br><span class=line> <span class=comment>// 如果 root 节点不同,就开始递归往下找与 subRoot 相同的起始节点,这里是或的关系,因为在左右子树任一找到一个就行</span></span><br><span class=line> <span class=keyword>return</span> isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);</span><br><span class=line> }</span><br><span class=line> <span class=comment>// 需要完全相同,也就是说不能像示例 2 那样多一个子节点这种,以及其他不同的情况,反正就是要完全一样</span></span><br><span class=line> <span class=keyword>public</span> <span class=type>boolean</span> <span class="title function_">isSameTree</span><span class=params>(TreeNode root, TreeNode subTree)</span> {</span><br><span class=line> <span class=comment>// 如果递归到这个节点都为空也认为是相同的</span></span><br><span class=line> <span class=keyword>if</span> (root == <span class=literal>null</span> && subTree == <span class=literal>null</span>) {</span><br><span class=line> <span class=keyword>return</span> <span class=literal>true</span>;</span><br><span class=line> }</span><br><span class=line> <span class=comment>// 因为有前面的判断,这里就隐含了 subTree != null 这个条件</span></span><br><span class=line> <span class=keyword>if</span> (root == <span class=literal>null</span>) {</span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br><span class=line> <span class=comment>// 也因为有前面的判断,这里就隐含了 root != null 这个条件</span></span><br><span class=line> <span class=keyword>if</span> (subTree == <span class=literal>null</span>) {</span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br><span class=line> <span class=comment>// 两个都不为空,但是值不相同,也是 false</span></span><br><span class=line> <span class=keyword>if</span> (root.val != subTree.val) {</span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br><span class=line> <span class=comment>// 跟节点相同,就开始递归判断左右子树,必须两者都相同</span></span><br><span class=line> <span class=keyword>return</span> isSameTree(root.left, subTree.left) && isSameTree(root.right, subTree.right);</span><br><span class=line> }</span><br></pre></table></figure></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/2024/01/21/Leetcode-25-Reverse-Nodes-in-k-Group-%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=/2024/01/21/Leetcode-25-Reverse-Nodes-in-k-Group-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ itemprop=url>Leetcode 25 Reverse Nodes in k-Group 题解分析-再解分析</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="创建时间:2024-01-21 15:09:47 / 修改时间:15:22:30" datetime=2024-01-21T15:09:47+08:00>2024-01-21</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 25 Reverse Nodes in k-Group 题解分析-再解分析" id=/2024/01/21/Leetcode-25-Reverse-Nodes-in-k-Group-%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=/2024/01/21/Leetcode-25-Reverse-Nodes-in-k-Group-%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=2024/01/21/Leetcode-25-Reverse-Nodes-in-k-Group-题解分析/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>上一次主要是给了一个解题方案,没有具体讲解,这次又做到了就来看下几种方案,链表转置一直是我比较疑惑的问题,特别是边界处理,而这个问题要把难度加大了<br>我先讲一下我一开始的思路和解题方法,首先就是写一个转置方法,就处理 k 个一组的内部转置,然后外部循环处理分组以及前后连接等问题,但是这里就涉及到一个问题,就是前后连接的话对于整个链表头,也就是第一个 k 元素组来说,头是个空的,就需要额外处理,一开始就是用判空做额外处理,然后在前后连接的时候也有一些困扰,看了自己的代码库发现其实之前也做过,而且发现这个思路跟以前做的还是一样的,只不过在处理 k 个元素内部的转置的时候有了点差异<br><img data-src=https://img.nicksxs.com/blog/0X0FuX-2024-01-21.9.11.15.png><br>一开始的思路是这样的,想了下其实还是比较有问题,从处理难度上来说,在 k 组内处理的时候一开始 A 节点会是悬空的,然后得处理到组内最后一个元素的时候再接上,逻辑会更复杂,而另一种思路就是直接把 A 先挪到 C 后面,这样每次只需要移动一个,可能思路上会更清晰一点<br><img data-src=https://img.nicksxs.com/blog/0X0FuX.png><br>也就是这样的,这种方案就是之前发过的题解代码,<a href=/2020/08/16/Leetcode-25-Reverse-Nodes-in-k-Group-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90-1/>上一篇</a><p>而最后这种则代码会简单一些,但是需要一定的理解成本,比较重要的一点是我们加了个虚拟的头结点,第一步会先获取下链表的总长度,然后在内循环里处理转置,重点就是分四步,<br>也就是图里的,第一步先把 cur 的下一个节点设置成 next 的 next 节点,这里就是图里 A 连接到 C,第二步是把 next 的 next 节点设置成虚拟头的 next节点,第三步是把 pre 的next 节点设置成 next,第四步是 next 往后移动<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br></pre><td class=code><pre><span class=line>cur.next = next.next;</span><br><span class=line>next.next = pre.next;</span><br><span class=line>pre.next = next;</span><br><span class=line>next = cur.next;</span><br></pre></table></figure><p><img data-src=https://img.nicksxs.com/blog/7uZX4o.png><br>在备注下代码</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/2024/01/21/%E8%81%8A%E4%B8%80%E4%B8%8B-Java-%E7%9A%84%E6%97%A5%E5%BF%97%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=/2024/01/21/%E8%81%8A%E4%B8%80%E4%B8%8B-Java-%E7%9A%84%E6%97%A5%E5%BF%97%E7%B3%BB%E5%88%97%E4%B8%89/ itemprop=url>聊一下 Java 的日志系列三</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="创建时间:2024-01-21 10:52:44" datetime=2024-01-21T10:52:44+08:00>2024-01-21</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="聊一下 Java 的日志系列三" id=/2024/01/21/%E8%81%8A%E4%B8%80%E4%B8%8B-Java-%E7%9A%84%E6%97%A5%E5%BF%97%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=/2024/01/21/%E8%81%8A%E4%B8%80%E4%B8%8B-Java-%E7%9A%84%E6%97%A5%E5%BF%97%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=2024/01/21/聊一下-Java-的日志系列三/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>上周因为一些事情没有更新在这里,是因为新电脑还没到,手头没有把移动硬盘里的 time machine 恢复出来的机器,所以单独更了一篇在新建的一个 cloudflare page 服务上,总体体验还可以,就是有个小点后面可以讲一下,继续完善下 Java 的这个日志,或者说主要讲的是 logback<br>前面讲了logback 的初始化逻辑,后面就是我最开始来看这个的逻辑,日志的滚动策略的触发逻辑<br>我们常规的记录日志的方式比如<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br></pre><td class=code><pre><span class=line>logger.info(<span class=string>"log some thing and biz info: {}"</span>,biz);</span><br></pre></table></figure><p>这里就调用了<br><code>ch.qos.logback.classic.Logger#info(java.lang.String, java.lang.Object)</code><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class=keyword>void</span> <span class="title function_">info</span><span class=params>(String format, Object arg)</span> {</span><br><span class=line> filterAndLog_1(FQCN, <span class=literal>null</span>, Level.INFO, format, arg, <span class=literal>null</span>);</span><br><span class=line>}</span><br></pre></table></figure><p>这里的 FQCN 就是这个类的全限定名<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class=keyword>static</span> <span class=keyword>final</span> <span class=type>String</span> <span class=variable>FQCN</span> <span class=operator>=</span> ch.qos.logback.classic.Logger.class.getName();</span><br></pre></table></figure><p>这个具体的 filterAndLog_1 方法还是在同一个 Logger 类里的<br><code>ch.qos.logback.classic.Logger#filterAndLog_1</code><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br></pre><td class=code><pre><span class=line><span class=keyword>private</span> <span class=keyword>void</span> <span class="title function_">filterAndLog_1</span><span class=params>(<span class=keyword>final</span> String localFQCN, <span class=keyword>final</span> Marker marker, <span class=keyword>final</span> Level level, <span class=keyword>final</span> String msg, <span class=keyword>final</span> Object param, <span class=keyword>final</span> Throwable t)</span> {</span><br><span class=line></span><br><span class=line> <span class=keyword>final</span> <span class=type>FilterReply</span> <span class=variable>decision</span> <span class=operator>=</span> loggerContext.getTurboFilterChainDecision_1(marker, <span class=built_in>this</span>, level, msg, param, t);</span><br><span class=line></span><br><span class=line> <span class=keyword>if</span> (decision == FilterReply.NEUTRAL) {</span><br><span class=line> <span class=keyword>if</span> (effectiveLevelInt > level.levelInt) {</span><br><span class=line> <span class=keyword>return</span>;</span><br><span class=line> }</span><br><span class=line> } <span class=keyword>else</span> <span class=keyword>if</span> (decision == FilterReply.DENY) {</span><br><span class=line> <span class=keyword>return</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> buildLoggingEventAndAppend(localFQCN, marker, level, msg, <span class=keyword>new</span> <span class="title class_">Object</span>[] { param }, t);</span><br><span class=line>}</span><br></pre></table></figure><p>这里面先是走过滤器逻辑,如果是拒绝的,那就不往下执行,也就不执行下面的写日志逻辑了,如果是中性的,那就判断日志级别是否符合,如果直接是拒绝就 return 了,如果是 ACCEPT 就往下执行了<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class=keyword>enum</span> <span class="title class_">FilterReply</span> {</span><br><span class=line> DENY, NEUTRAL, ACCEPT;</span><br><span class=line>}</span><br></pre></table></figure><p>然后继续调用同样的类的方法<br><code>ch.qos.logback.classic.Logger#buildLoggingEventAndAppend</code><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br></pre><td class=code><pre><span class=line><span class=keyword>private</span> <span class=keyword>void</span> <span class="title function_">buildLoggingEventAndAppend</span><span class=params>(<span class=keyword>final</span> String localFQCN, <span class=keyword>final</span> Marker marker, <span class=keyword>final</span> Level level, <span class=keyword>final</span> String msg, <span class=keyword>final</span> Object[] params,</span></span><br><span class=line><span class=params> <span class=keyword>final</span> Throwable t)</span> {</span><br><span class=line> <span class=type>LoggingEvent</span> <span class=variable>le</span> <span class=operator>=</span> <span class=keyword>new</span> <span class="title class_">LoggingEvent</span>(localFQCN, <span class=built_in>this</span>, level, msg, t, params);</span><br><span class=line> le.setMarker(marker);</span><br><span class=line> callAppenders(le);</span><br><span class=line>}</span><br></pre></table></figure><p>先把日志包装成 <code>LoggingEvent</code> ,然后调用<br><code>ch.qos.logback.classic.Logger#callAppenders</code><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class=keyword>void</span> <span class="title function_">callAppenders</span><span class=params>(ILoggingEvent event)</span> {</span><br><span class=line> <span class=type>int</span> <span class=variable>writes</span> <span class=operator>=</span> <span class=number>0</span>;</span><br><span class=line> <span class=keyword>for</span> (<span class=type>Logger</span> <span class=variable>l</span> <span class=operator>=</span> <span class=built_in>this</span>; l != <span class=literal>null</span>; l = l.parent) {</span><br><span class=line> writes += l.appendLoopOnAppenders(event);</span><br><span class=line> <span class=keyword>if</span> (!l.additive) {</span><br><span class=line> <span class=keyword>break</span>;</span><br><span class=line> }</span><br><span class=line> }</span><br><span class=line> <span class=comment>// No appenders in hierarchy</span></span><br><span class=line> <span class=keyword>if</span> (writes == <span class=number>0</span>) {</span><br><span class=line> loggerContext.noAppenderDefinedWarning(<span class=built_in>this</span>);</span><br><span class=line> }</span><br><span class=line>}</span><br></pre></table></figure><p>这里会按 Logger 调用 <code>appendLoopOnAppenders</code><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br></pre><td class=code><pre><span class=line><span class=keyword>private</span> <span class=type>int</span> <span class="title function_">appendLoopOnAppenders</span><span class=params>(ILoggingEvent event)</span> {</span><br><span class=line> <span class=keyword>if</span> (aai != <span class=literal>null</span>) {</span><br><span class=line> <span class=keyword>return</span> aai.appendLoopOnAppenders(event);</span><br><span class=line> } <span class=keyword>else</span> {</span><br><span class=line> <span class=keyword>return</span> <span class=number>0</span>;</span><br><span class=line> }</span><br></pre></table></figure><p>继续调用事件的<br><code>ch.qos.logback.core.spi.AppenderAttachableImpl#appendLoopOnAppenders</code><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class=type>int</span> <span class="title function_">appendLoopOnAppenders</span><span class=params>(E e)</span> {</span><br><span class=line> <span class=type>int</span> <span class=variable>size</span> <span class=operator>=</span> <span class=number>0</span>;</span><br><span class=line> <span class=keyword>final</span> Appender&LTE>[] appenderArray = appenderList.asTypedArray();</span><br><span class=line> <span class=keyword>final</span> <span class=type>int</span> <span class=variable>len</span> <span class=operator>=</span> appenderArray.length;</span><br><span class=line> <span class=keyword>for</span> (<span class=type>int</span> <span class=variable>i</span> <span class=operator>=</span> <span class=number>0</span>; i < len; i++) {</span><br><span class=line> appenderArray[i].doAppend(e);</span><br><span class=line> size++;</span><br><span class=line> }</span><br><span class=line> <span class=keyword>return</span> size;</span><br><span class=line>}</span><br></pre></table></figure><p>因为 Logger 里有关联 appender,就具体调用关联的 appender 来添加日志<br>然后就接着调用<br><code>ch.qos.logback.core.UnsynchronizedAppenderBase#doAppend</code> 方法<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br><span class=line>15</span><br><span class=line>16</span><br><span class=line>17</span><br><span class=line>18</span><br><span class=line>19</span><br><span class=line>20</span><br><span class=line>21</span><br><span class=line>22</span><br><span class=line>23</span><br><span class=line>24</span><br><span class=line>25</span><br><span class=line>26</span><br><span class=line>27</span><br><span class=line>28</span><br><span class=line>29</span><br><span class=line>30</span><br><span class=line>31</span><br><span class=line>32</span><br><span class=line>33</span><br><span class=line>34</span><br></pre><td class=code><pre><span class=line><span class=keyword>public</span> <span class=keyword>void</span> <span class="title function_">doAppend</span><span class=params>(E eventObject)</span> {</span><br><span class=line> <span class=comment>// WARNING: The guard check MUST be the first statement in the</span></span><br><span class=line> <span class=comment>// doAppend() method.</span></span><br><span class=line></span><br><span class=line> <span class=comment>// prevent re-entry.</span></span><br><span class=line> <span class=keyword>if</span> (Boolean.TRUE.equals(guard.get())) {</span><br><span class=line> <span class=keyword>return</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> <span class=keyword>try</span> {</span><br><span class=line> guard.set(Boolean.TRUE);</span><br><span class=line></span><br><span class=line> <span class=keyword>if</span> (!<span class=built_in>this</span>.started) {</span><br><span class=line> <span class=keyword>if</span> (statusRepeatCount++ < ALLOWED_REPEATS) {</span><br><span class=line> addStatus(<span class=keyword>new</span> <span class="title class_">WarnStatus</span>(<span class=string>"Attempted to append to non started appender ["</span> + name + <span class=string>"]."</span>, <span class=built_in>this</span>));</span><br><span class=line> }</span><br><span class=line> <span class=keyword>return</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> <span class=keyword>if</span> (getFilterChainDecision(eventObject) == FilterReply.DENY) {</span><br><span class=line> <span class=keyword>return</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> <span class=comment>// ok, we now invoke derived class' implementation of append</span></span><br><span class=line> <span class=built_in>this</span>.append(eventObject);</span><br><span class=line></span><br><span class=line> } <span class=keyword>catch</span> (Exception e) {</span><br><span class=line> <span class=keyword>if</span> (exceptionCount++ < ALLOWED_REPEATS) {</span><br><span class=line> addError(<span class=string>"Appender ["</span> + name + <span class=string>"] failed to append."</span>, e);</span><br><span class=line> }</span><br><span class=line> } <span class=keyword>finally</span> {</span><br><span class=line> guard.set(Boolean.FALSE);</span><br><span class=line> }</span><br><span class=line> }</span><br></pre></table></figure><p>这里先判断了 guard 的状态,guard 是个 ThreadLocal,是为了拦截异常的无限循环调用,这里有些疑惑的,看了一圈可能相关的是前面的 Logger 会往父级查找,然后如果不同层级的 Logger 关联了相同的 appender 的话,或者这个 doAppend 又被其他 appender 调用了,就可能会出现循环调用,然后会在开始实际的 append的之前先设置 guard 状态,<br>然后再执行 append,这里会走到<br><code>ch.qos.logback.core.OutputStreamAppender#append</code><figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br></pre><td class=code><pre><span class=line><span class=meta>@Override</span></span><br><span class=line><span class=keyword>protected</span> <span class=keyword>void</span> <span class="title function_">append</span><span class=params>(E eventObject)</span> {</span><br><span class=line> <span class=keyword>if</span> (!isStarted()) {</span><br><span class=line> <span class=keyword>return</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> subAppend(eventObject);</span><br><span class=line>}</span><br></pre></table></figure><p>忘了补充下,我们这里使用的是<br><code>ch.qos.logback.core.rolling.RollingFileAppender</code><br>接下去就是调用的 <code>RollingFileAppender</code><code>subAppend</code> 方法<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br><span class=line>15</span><br></pre><td class=code><pre><span class=line><span class=meta>@Override</span></span><br><span class=line><span class=keyword>protected</span> <span class=keyword>void</span> <span class="title function_">subAppend</span><span class=params>(E event)</span> {</span><br><span class=line> <span class=comment>// The roll-over check must precede actual writing. This is the</span></span><br><span class=line> <span class=comment>// only correct behavior for time driven triggers.</span></span><br><span class=line></span><br><span class=line> <span class=comment>// We need to synchronize on triggeringPolicy so that only one rollover</span></span><br><span class=line> <span class=comment>// occurs at a time</span></span><br><span class=line> <span class=keyword>synchronized</span> (triggeringPolicy) {</span><br><span class=line> <span class=keyword>if</span> (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) {</span><br><span class=line> rollover();</span><br><span class=line> }</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> <span class=built_in>super</span>.subAppend(event);</span><br><span class=line>}</span><br></pre></table></figure><p>这里就会先判断是否触发事件,<br>而这里就是主要的逻辑,看是否需要走 rollover,也就是具体的滚动逻辑<figure class="highlight java"><table><tr><td class=gutter><pre><span class=line>1</span><br><span class=line>2</span><br><span class=line>3</span><br><span class=line>4</span><br><span class=line>5</span><br><span class=line>6</span><br><span class=line>7</span><br><span class=line>8</span><br><span class=line>9</span><br><span class=line>10</span><br><span class=line>11</span><br><span class=line>12</span><br><span class=line>13</span><br><span class=line>14</span><br><span class=line>15</span><br><span class=line>16</span><br><span class=line>17</span><br><span class=line>18</span><br><span class=line>19</span><br><span class=line>20</span><br><span class=line>21</span><br><span class=line>22</span><br><span class=line>23</span><br><span class=line>24</span><br><span class=line>25</span><br><span class=line>26</span><br><span class=line>27</span><br><span class=line>28</span><br><span class=line>29</span><br><span class=line>30</span><br><span class=line>31</span><br><span class=line>32</span><br><span class=line>33</span><br><span class=line>34</span><br><span class=line>35</span><br><span class=line>36</span><br><span class=line>37</span><br></pre><td class=code><pre><span class=line><span class=meta>@Override</span></span><br><span class=line> <span class=keyword>public</span> <span class=type>boolean</span> <span class="title function_">isTriggeringEvent</span><span class=params>(File activeFile, <span class=keyword>final</span> E event)</span> {</span><br><span class=line></span><br><span class=line> <span class=type>long</span> <span class=variable>time</span> <span class=operator>=</span> getCurrentTime();</span><br><span class=line></span><br><span class=line> <span class=comment>// first check for roll-over based on time</span></span><br><span class=line> <span class=keyword>if</span> (time >= nextCheck) {</span><br><span class=line> <span class=type>Date</span> <span class=variable>dateInElapsedPeriod</span> <span class=operator>=</span> dateInCurrentPeriod;</span><br><span class=line> elapsedPeriodsFileName = tbrp.fileNamePatternWithoutCompSuffix.convertMultipleArguments(dateInElapsedPeriod, currentPeriodsCounter);</span><br><span class=line> currentPeriodsCounter = <span class=number>0</span>;</span><br><span class=line> setDateInCurrentPeriod(time);</span><br><span class=line> computeNextCheck();</span><br><span class=line> <span class=keyword>return</span> <span class=literal>true</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> <span class=comment>// next check for roll-over based on size</span></span><br><span class=line> <span class=keyword>if</span> (invocationGate.isTooSoon(time)) {</span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> <span class=keyword>if</span> (activeFile == <span class=literal>null</span>) {</span><br><span class=line> addWarn(<span class=string>"activeFile == null"</span>);</span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br><span class=line> <span class=keyword>if</span> (maxFileSize == <span class=literal>null</span>) {</span><br><span class=line> addWarn(<span class=string>"maxFileSize = null"</span>);</span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br><span class=line> <span class=keyword>if</span> (activeFile.length() >= maxFileSize.getSize()) {</span><br><span class=line></span><br><span class=line> elapsedPeriodsFileName = tbrp.fileNamePatternWithoutCompSuffix.convertMultipleArguments(dateInCurrentPeriod, currentPeriodsCounter);</span><br><span class=line> currentPeriodsCounter++;</span><br><span class=line> <span class=keyword>return</span> <span class=literal>true</span>;</span><br><span class=line> }</span><br><span class=line></span><br><span class=line> <span class=keyword>return</span> <span class=literal>false</span>;</span><br><span class=line> }</span><br></pre></table></figure><p>这里主要就用到了 nextCheck 判断,如果通过判断就可以执行滚动了,然后就是后面的判断,是否太快了,也就是 isTooSoon 然后再看当前的活跃日志以及最大文件大小是否设置,然后如果当前的活跃日志的大小超过了配置也会触发滚动</div><footer class=post-footer><div class=post-eof></div></footer></article></div><nav class=pagination><a class="extend prev" aria-label=上一页 href=/page/2/ rel=prev title=上一页><i class="fa fa-angle-left"></i></a><a class=page-number href=/>1</a><a class=page-number href=/page/2/>2</a><span class="page-number current">3</span><a class=page-number href=/page/4/>4</a><span class=space></span><a class=page-number href=/page/53/>53</a><a class="extend next" aria-label=下一页 href=/page/4/ 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=https://beian.mps.gov.cn/#/query/webSearch?code=33010602011094 rel=noopener target=_blank>浙公网安备 33010602011094号</a></div><div class=copyright>© <span itemprop=copyrightYear>2024</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="在 GitHub 上关注我" title="在 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-ytMJGN3toR+a84u7g7NuHm91VIR06Q41kMWDr2pq7Zo= src=https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.umd.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-DABVk+hYj0mdUzo+7ViJC6cwLahQIejFvC+my2M/wfM= src=https://cdnjs.cloudflare.com/ajax/libs/algoliasearch/4.20.0/algoliasearch-lite.umd.js></script><script crossorigin=anonymous integrity=sha256-9242vN47QUX50UG5Gf5XDO1YREWCEJRyXHofh5fsl24= src=https://cdnjs.cloudflare.com/ajax/libs/instantsearch.js/4.60.0/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/3/"}</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>