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.
 
 

457 lines
175 KiB

<!doctypehtml><html lang=zh-CN><meta charset=UTF-8><meta content=width=device-width name=viewport><meta content=#222 name=theme-color><meta content="Hexo 6.3.0" name=generator><link href=https://fonts.googleapis.com rel=preconnect><link href=https://cdnjs.cloudflare.com rel=preconnect><link href=/images/apple-touch-icon-next.png rel=apple-touch-icon sizes=180x180><link href=/images/favicon-32x32-next.png rel=icon sizes=32x32 type=image/png><link href=/images/favicon-16x16-next.png rel=icon sizes=16x16 type=image/png><link color=#222 href=/images/logo.svg rel=mask-icon><meta content=2X6S9P7CAjXjVvw8YyQR8pCu-B0oEu7O9quLgxXuWyA name=google-site-verification><meta content=dV8JGNzi0c name=baidu-site-verification><script>setTimeout(function(){var d=document.createElement("script");d.setAttribute("data-ad-client","ca-pub-7480618470784058"),d.async=!0,d.src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js",document.body.appendChild(d)},5e3),window.addEventListener?window.addEventListener("load",downloadJsAtOnload,!1):window.attachEvent?window.attachEvent("onload",downloadJsAtOnload):window.onload=downloadJsAtOnload</script><style>:root{--body-bg-color:#f5f7f9;--content-bg-color:#fff;--card-bg-color:#f5f5f5;--text-color:#555;--blockquote-color:#666;--link-color:#555;--link-hover-color:#222;--brand-color:#fff;--brand-hover-color:#fff;--table-row-odd-bg-color:#f9f9f9;--table-row-hover-bg-color:#f5f5f5;--menu-item-bg-color:#f5f5f5;--theme-color:#222;--btn-default-bg:#fff;--btn-default-color:#555;--btn-default-border-color:#555;--btn-default-hover-bg:#222;--btn-default-hover-color:#fff;--btn-default-hover-border-color:#222;--highlight-background:#f3f3f3;--highlight-foreground:#444;--highlight-gutter-background:#e1e1e1;--highlight-gutter-foreground:#555;color-scheme:light}html{line-height:1.15;-webkit-text-size-adjust:100%}details,main{display:block}pre{font-size:1em;overflow:auto;padding:10px;position:relative}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}.table-container,textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}summary{display:list-item}[hidden],template{display:none}::selection{background:#262a30;color:#eee}body,html{height:100%}body{margin:0;background:var(--body-bg-color);box-sizing:border-box;color:var(--text-color);font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-size:1.2em;line-height:2;min-height:100%;position:relative;transition:padding .2s ease-in-out}h1,h2,h3,h4,h5,h6{font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-weight:700;line-height:1.5;margin:30px 0 15px}h1{font-size:1.5em}h2{font-size:1.375em}h3{font-size:1.25em}h4{font-size:1.125em}h5{font-size:1em}h6{font-size:.875em}p{margin:0 0 20px}a{background:0 0;border-bottom:1px solid #999;color:var(--link-color);cursor:pointer;outline:0;text-decoration:none;overflow-wrap:break-word}a:hover{border-bottom-color:var(--link-hover-color);color:var(--link-hover-color)}embed,iframe,img,video{display:block;margin-left:auto;margin-right:auto;max-width:100%}hr{box-sizing:content-box;overflow:visible;background-image:repeating-linear-gradient(-45deg,#ddd,#ddd 4px,transparent 4px,transparent 8px);border:0;height:3px;margin:40px 0}blockquote{border-left:4px solid #ddd;color:var(--blockquote-color);margin:0;padding:0 15px}blockquote cite::before{content:'-';padding:0 5px}dt{font-weight:700}dd{margin:0;padding:0}table{border-collapse:collapse;border-spacing:0;font-size:.875em;margin:0 0 20px;width:100%}tbody tr:nth-of-type(odd){background:var(--table-row-odd-bg-color)}tbody tr:hover{background:var(--table-row-hover-bg-color)}caption,td,th{padding:8px}td,th{border:1px solid #ddd;border-bottom:3px solid #ddd}th{font-weight:700;padding-bottom:10px}td{border-bottom-width:1px}.btn{background:var(--btn-default-bg);border:2px solid var(--btn-default-border-color);border-radius:2px;color:var(--btn-default-color);display:inline-block;font-size:.875em;line-height:2;padding:0 20px;transition:background-color .2s ease-in-out}.btn:hover{background:var(--btn-default-hover-bg);border-color:var(--btn-default-hover-border-color);color:var(--btn-default-hover-color)}.btn+.btn{margin:0 0 8px 8px}.btn .fa-fw{text-align:left;width:1.285714285714286em}.toggle{line-height:0}.toggle .toggle-line{background:#fff;display:block;height:2px;left:0;position:relative;top:0;transition:.4s;width:100%}.toggle .toggle-line:first-child{margin-top:1px}.toggle .toggle-line:not(:first-child){margin-top:4px}.toggle.toggle-arrow :first-child{left:50%;top:2px;transform:rotate(45deg);width:50%}.toggle.toggle-arrow :last-child{left:50%;top:-2px;transform:rotate(-45deg);width:50%}.toggle.toggle-close :nth-child(2){opacity:0}.toggle.toggle-close :first-child{top:6px;transform:rotate(45deg)}.toggle.toggle-close :last-child{top:-6px;transform:rotate(-45deg)}code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}.highlight:hover .copy-btn,pre:hover .copy-btn{opacity:1}figure.highlight .table-container{position:relative;border-radius:0 0 5px 5px}.copy-btn{color:#333;cursor:pointer;line-height:1.6;opacity:0;padding:2px 6px;position:absolute;transition:opacity .2s ease-in-out;color:var(--highlight-foreground);font-size:14px;right:0;top:2px}figure.highlight{border-radius:5px;box-shadow:0 10px 30px 0 rgba(0,0,0,.4);padding-top:30px;overflow:auto;position:relative}figure.highlight::before{background:#fc625d;box-shadow:20px 0 #fdbc40,40px 0 #35cd4b;left:12px;margin-top:-20px;position:absolute;border-radius:50%;content:' ';height:12px;width:12px}code,figure.highlight,kbd,pre{background:var(--highlight-background);color:var(--highlight-foreground)}figure.highlight,pre{line-height:1.6;margin:0 auto 20px}figure.highlight figcaption,pre .caption,pre figcaption{background:var(--highlight-gutter-background);color:var(--highlight-foreground);display:flow-root;font-size:.875em;line-height:1.2;padding:.5em}figure.highlight figcaption a,pre .caption a,pre figcaption a{color:var(--highlight-foreground);float:right}figure.highlight figcaption a:hover,pre .caption a:hover,pre figcaption a:hover{border-bottom-color:var(--highlight-foreground)}code,pre{font-family:consolas,Menlo,monospace,'PingFang SC','Microsoft YaHei'}code{border-radius:3px;font-size:.875em;padding:2px 4px;overflow-wrap:break-word}kbd{border:2px solid #ccc;border-radius:.2em;box-shadow:.1em .1em .2em rgba(0,0,0,.1);font-family:inherit;padding:.1em .3em;white-space:nowrap}figure.highlight pre{border:0;margin:0;padding:10px 0}figure.highlight table{border:0;margin:0;width:auto}figure.highlight td{border:0;padding:0}figure.highlight .gutter{-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}figure.highlight .gutter pre{background:var(--highlight-gutter-background);color:var(--highlight-gutter-foreground);padding-left:10px;padding-right:10px;text-align:right}figure.highlight .code pre{padding-left:10px;width:100%}figure.highlight .marked{background:rgba(0,0,0,.3)}pre .caption,pre figcaption{margin-bottom:10px}.gist table{width:auto}.gist table td{border:0}pre code{background:0 0;padding:0;text-shadow:none}.blockquote-center{border-left:0;margin:40px 0;padding:0;position:relative;text-align:center}.blockquote-center::after,.blockquote-center::before{left:0;line-height:1;opacity:.6;position:absolute;width:100%}.blockquote-center::before{border-top:1px solid #ccc;text-align:left;top:-20px;content:'\f10d';font-family:'Font Awesome 6 Free';font-weight:900}.blockquote-center::after{border-bottom:1px solid #ccc;bottom:-20px;text-align:right;content:'\f10e';font-family:'Font Awesome 6 Free';font-weight:900}.blockquote-center div,.blockquote-center p{text-align:center}.group-picture{margin-bottom:20px}.group-picture .group-picture-row{display:flex;gap:3px;margin-bottom:3px}.group-picture .group-picture-column{flex:1}.group-picture .group-picture-column img{height:100%;margin:0;object-fit:cover;width:100%}.post-body .label{color:#555;padding:0 2px}.post-body .label.default{background:#f0f0f0}.post-body .label.primary{background:#efe6f7}.post-body .label.info{background:#e5f2f8}.post-body .label.success{background:#e7f4e9}.post-body .label.warning{background:#fcf6e1}.post-body .label.danger{background:#fae8eb}.post-body .link-grid{display:grid;grid-gap:1.5rem;gap:1.5rem;grid-template-columns:1fr 1fr;margin-bottom:20px;padding:1rem}.post-body .link-grid .link-grid-container{border:solid #ddd;box-shadow:1rem 1rem .5rem rgba(0,0,0,.5);min-height:5rem;min-width:0;padding:.5rem;position:relative;transition:background .3s}.post-body .link-grid .link-grid-container:hover{animation:.5s next-shake;background:var(--card-bg-color)}.post-body .link-grid .link-grid-container:active{box-shadow:.5rem .5rem .25rem rgba(0,0,0,.5);transform:translate(.2rem,.2rem)}.post-body .link-grid .link-grid-container .link-grid-image{border:1px solid #ddd;border-radius:50%;box-sizing:border-box;height:5rem;padding:3px;position:absolute;width:5rem}.post-body .link-grid .link-grid-container p{margin:0 1rem 0 6rem}.post-body .link-grid .link-grid-container p:first-of-type{font-size:1.2em}.post-body .link-grid .link-grid-container p:last-of-type{font-size:.8em;line-height:1.3rem;opacity:.7}.post-body .link-grid .link-grid-container a{border:0;height:100%;left:0;position:absolute;top:0;width:100%}@keyframes next-shake{0%{transform:translate(1pt,1pt) rotate(0)}10%{transform:translate(-1pt,-2pt) rotate(-1deg)}20%{transform:translate(-3pt,0) rotate(1deg)}30%{transform:translate(3pt,2pt) rotate(0)}40%{transform:translate(1pt,-1pt) rotate(1deg)}50%{transform:translate(-1pt,2pt) rotate(-1deg)}60%{transform:translate(-3pt,1pt) rotate(0)}70%{transform:translate(3pt,1pt) rotate(-1deg)}80%{transform:translate(-1pt,-1pt) rotate(1deg)}90%{transform:translate(1pt,2pt) rotate(0)}100%{transform:translate(1pt,-2pt) rotate(-1deg)}}.post-body .note{border-radius:3px;margin-bottom:20px;padding:1em;position:relative;border:1px solid #eee;border-left-width:5px}.post-body .note summary{cursor:pointer;outline:0}.post-body .note summary p{display:inline}.post-body .note h2,.post-body .note h3,.post-body .note h4,.post-body .note h5,.post-body .note h6{border-bottom:initial;margin:0;padding-top:0}.post-body .note :first-child{margin-top:0}.post-body .note :last-child{margin-bottom:0}.post-body .note.default{border-left-color:#777}.post-body .note.default h2,.post-body .note.default h3,.post-body .note.default h4,.post-body .note.default h5,.post-body .note.default h6{color:#777}.post-body .note.primary{border-left-color:#6f42c1}.post-body .note.primary h2,.post-body .note.primary h3,.post-body .note.primary h4,.post-body .note.primary h5,.post-body .note.primary h6{color:#6f42c1}.post-body .note.info{border-left-color:#428bca}.post-body .note.info h2,.post-body .note.info h3,.post-body .note.info h4,.post-body .note.info h5,.post-body .note.info h6{color:#428bca}.post-body .note.success{border-left-color:#5cb85c}.post-body .note.success h2,.post-body .note.success h3,.post-body .note.success h4,.post-body .note.success h5,.post-body .note.success h6{color:#5cb85c}.post-body .note.warning{border-left-color:#f0ad4e}.post-body .note.warning h2,.post-body .note.warning h3,.post-body .note.warning h4,.post-body .note.warning h5,.post-body .note.warning h6{color:#f0ad4e}.post-body .note.danger{border-left-color:#d9534f}.post-body .note.danger h2,.post-body .note.danger h3,.post-body .note.danger h4,.post-body .note.danger h5,.post-body .note.danger h6{color:#d9534f}.post-body .tabs{margin-bottom:20px}.post-body .tabs,.tabs-comment{padding-top:10px}.post-body .tabs ul.nav-tabs,.tabs-comment ul.nav-tabs{background:var(--content-bg-color);display:flex;display:flex;flex-wrap:wrap;justify-content:center;margin:0;padding:0;position:-webkit-sticky;position:sticky;top:0;z-index:5}.post-body .tabs ul.nav-tabs li.tab,.tabs-comment ul.nav-tabs li.tab{border-bottom:1px solid #ddd;border-left:1px solid transparent;border-right:1px solid transparent;border-radius:0;border-top:3px solid transparent;flex-grow:1;list-style-type:none}@media (max-width:413px){.post-body .tabs ul.nav-tabs,.tabs-comment ul.nav-tabs{display:block;margin-bottom:5px}.post-body .tabs ul.nav-tabs li.tab,.tabs-comment ul.nav-tabs li.tab{border-bottom:1px solid transparent;border-left:3px solid transparent;border-right:1px solid transparent;border-top:1px solid transparent;border-radius:0}}.post-body .tabs ul.nav-tabs li.tab a,.tabs-comment ul.nav-tabs li.tab a{border-bottom:initial;display:block;line-height:1.8;padding:.25em .75em;text-align:center;transition:.2s ease-out}.post-body .tabs ul.nav-tabs li.tab a i,.tabs-comment ul.nav-tabs li.tab a i{width:1.285714285714286em}.post-body .tabs ul.nav-tabs li.tab.active,.tabs-comment ul.nav-tabs li.tab.active{border-color:#fc6423 #ddd transparent}@media (max-width:413px){.post-body .tabs ul.nav-tabs li.tab.active,.tabs-comment ul.nav-tabs li.tab.active{border-color:#ddd #ddd #ddd #fc6423}}.post-body .tabs ul.nav-tabs li.tab.active a,.tabs-comment ul.nav-tabs li.tab.active a{cursor:default}.post-body .tabs .tab-content,.tabs-comment .tab-content{border:1px solid #ddd;border-radius:0;border-top-color:transparent}@media (max-width:413px){.post-body .tabs .tab-content,.tabs-comment .tab-content{border-radius:0;border-top-color:#ddd}}.post-body .tabs .tab-content .tab-pane,.tabs-comment .tab-content .tab-pane{padding:20px 20px 0}.post-body .tabs .tab-content .tab-pane:not(.active),.tabs-comment .tab-content .tab-pane:not(.active){display:none}.pagination .next,.pagination .page-number,.pagination .prev,.pagination .space{display:inline-block;margin:-1px 10px 0;padding:0 10px}.algolia-pagination .current .page-number,.pagination .page-number.current{background:#ccc;border-color:#ccc;color:var(--content-bg-color)}.pagination{border-top:1px solid #eee;margin:120px 0 0;text-align:center}.pagination .next,.pagination .page-number,.pagination .prev{border-bottom:0;border-top:1px solid #eee;transition:border-color .2s ease-in-out}.pagination .next:hover,.pagination .page-number:hover,.pagination .prev:hover{border-top-color:var(--link-hover-color)}@media (max-width:767px){.post-body .link-grid{grid-template-columns:1fr}.pagination .next,.pagination .page-number,.pagination .prev,.pagination .space{margin:0 5px}.pagination{border-top:0}.pagination .next,.pagination .page-number,.pagination .prev{border-bottom:1px solid #eee;border-top:0}.pagination .next:hover,.pagination .page-number:hover,.pagination .prev:hover{border-bottom-color:var(--link-hover-color)}.site-meta{text-align:center}}.pagination .space{margin:0;padding:0}.comments{margin-top:60px;overflow:hidden}.comment-button-group{display:flex;display:flex;flex-wrap:wrap;justify-content:center;justify-content:center;margin:1em 0}.comment-button-group .comment-button{margin:.1em .2em}.comment-button-group .comment-button.active{background:var(--btn-default-hover-bg);border-color:var(--btn-default-hover-border-color);color:var(--btn-default-hover-color)}.comment-position{display:none}.comment-position.active{display:block}.tabs-comment{margin-top:4em;padding-top:0}.tabs-comment .comments{margin-top:0;padding-top:0}.headband{background:var(--theme-color);height:3px}@media (max-width:991px){.headband{display:none}}.site-brand-container{display:flex;flex-shrink:0;padding:0 10px}.use-motion .column,.use-motion .site-brand-container .toggle{opacity:0}.site-meta{flex-grow:1;text-align:center}.custom-logo-image{margin-top:20px}@media (max-width:991px){.custom-logo-image{display:none}}.brand{border-bottom:0;color:var(--brand-color);display:inline-block;padding:0}.brand:hover{color:var(--brand-hover-color)}.site-title{font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-size:1.375em;font-weight:400;line-height:1.5;margin:0}.site-subtitle{color:#ddd;font-size:.8125em;margin:10px 10px 0}.use-motion .custom-logo-image,.use-motion .site-subtitle,.use-motion .site-title{opacity:0;position:relative;top:-10px}.site-nav-right,.site-nav-toggle{display:none}.site-nav-right .toggle,.site-nav-toggle .toggle{color:var(--text-color);padding:10px;width:22px}.site-nav-right .toggle .toggle-line,.site-nav-toggle .toggle .toggle-line{background:var(--text-color);border-radius:1px}@media (max-width:767px){.site-nav-right,.site-nav-toggle{display:flex;flex-direction:column;justify-content:center}.site-nav{--scroll-height:0;height:0;overflow:hidden;transition:height .2s ease-in-out}body:not(.site-nav-on) .site-nav .animated{animation:none}body.site-nav-on .site-nav{height:var(--scroll-height)}}.menu{margin:0;padding:1em 0;text-align:center}.menu-item{display:inline-block;list-style:none;margin:0 10px}@media (max-width:767px){.menu-item{display:block;margin-top:10px}.menu-item.menu-item-search{display:none}}.menu-item a{border-bottom:0;display:block;font-size:.8125em;transition:border-color .2s ease-in-out}.menu-item a.menu-item-active,.menu-item a:hover{background:var(--menu-item-bg-color)}.menu-item .fa,.menu-item .fab,.menu-item .far,.menu-item .fas{margin-right:8px}.menu-item .badge{display:inline-block;font-weight:700;line-height:1;margin-left:.35em;margin-top:.35em;text-align:center;white-space:nowrap}.use-motion .menu-item{visibility:hidden}.github-corner :hover .octo-arm{animation:560ms ease-in-out octocat-wave}.github-corner svg{color:#fff;fill:var(--theme-color);position:absolute;right:0;top:0;z-index:5}@media (max-width:991px){.github-corner{display:none}.github-corner svg{color:var(--theme-color);fill:#fff}.github-corner .github-corner:hover .octo-arm{animation:none}.github-corner .github-corner .octo-arm{animation:560ms ease-in-out octocat-wave}}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}.sidebar-inner{color:#999;padding:18px 10px;text-align:center;display:flex;flex-direction:column;justify-content:center}.cc-license .cc-opacity{border-bottom:0;opacity:.7}.cc-license .cc-opacity:hover{opacity:.9}.cc-license img{display:inline-block}.site-author-image{border:1px solid #eee;max-width:120px;padding:2px}.site-author-name{color:var(--text-color);font-weight:600;margin:0}.site-description{color:#999;font-size:.8125em;margin-top:0}.links-of-author a{font-size:.8125em}.links-of-author .fa,.links-of-author .fab,.links-of-author .far,.links-of-author .fas{margin-right:2px}.sidebar .sidebar-button:not(:first-child){margin-top:15px}.sidebar .sidebar-button button{background:0 0;cursor:pointer;line-height:2;padding:0 15px;border-radius:4px}.sidebar .sidebar-button button .fa,.sidebar .sidebar-button button .fab,.sidebar .sidebar-button button .far,.sidebar .sidebar-button button .fas{margin-right:5px}.links-of-blogroll{font-size:.8125em}.links-of-blogroll-title{font-size:.875em;font-weight:600}.links-of-blogroll-list{list-style:none;margin:0;padding:0}.sidebar-nav{display:none;margin:0;padding-bottom:20px;padding-left:0}.sidebar-nav-active .sidebar-nav{display:block}.sidebar-nav li{border-bottom:1px solid transparent;color:var(--text-color);cursor:pointer;display:inline-block;font-size:.875em}.sidebar-nav li.sidebar-nav-overview{margin-left:10px}.sidebar-nav li:hover{color:#fc6423}.sidebar-overview-active .sidebar-nav-overview,.sidebar-toc-active .sidebar-nav-toc{border-bottom-color:#fc6423;color:#fc6423}.sidebar-overview-active .sidebar-nav-overview:hover,.sidebar-toc-active .sidebar-nav-toc:hover{color:#fc6423}.sidebar-panel-container{flex:1;overflow-x:hidden;overflow-y:auto}.sidebar-panel{display:none}.sidebar-overview-active .site-overview-wrap{display:flex;flex-direction:column;justify-content:center;gap:10px}.sidebar-toc-active .post-toc-wrap{display:block}.sidebar-toggle{bottom:61px;height:16px;padding:5px;width:16px;background:#222;cursor:pointer;opacity:.6;position:fixed;z-index:30;right:30px}.sidebar-toggle:hover{opacity:.8}@media (max-width:991px){.sidebar-toggle{right:20px;opacity:.8}}.sidebar-toggle:hover .toggle-line{background:#fc6423}@media (any-hover:hover){body:not(.sidebar-active) .sidebar-toggle:hover :first-child{left:50%;top:2px;transform:rotate(45deg);width:50%}body:not(.sidebar-active) .sidebar-toggle:hover :last-child{left:50%;top:-2px;transform:rotate(-45deg);width:50%}}.sidebar-active .sidebar-toggle :nth-child(2){opacity:0}.sidebar-active .sidebar-toggle :first-child{top:6px;transform:rotate(45deg)}.sidebar-active .sidebar-toggle :last-child{top:-6px;transform:rotate(-45deg)}.post-toc{font-size:.875em}.post-toc ol{list-style:none;margin:0;padding:0 2px 5px 10px;text-align:left}.post-toc ol>ol{padding-left:0}.post-toc ol a{transition:.2s ease-in-out}.post-toc .nav-item{line-height:1.8;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.post-toc .nav .nav-child{display:none}.post-toc .nav .active-current>.nav-child,.post-toc .nav .active-current>.nav-child>.nav-item,.post-toc .nav .active>.nav-child{display:block}.post-toc .nav .active>a{border-bottom-color:#fc6423;color:#fc6423}.post-toc .nav .active-current>a,.post-toc .nav .active-current>a:hover{color:#fc6423}.site-state{display:flex;flex-wrap:wrap;justify-content:center;line-height:1.4}.site-state-item a{border-bottom:0;display:block}.site-state-item-count{display:block;font-size:1em;font-weight:600}.site-state-item-name{color:#999;font-size:.8125em}.sidebar-post-related{font-size:.8125em;padding:18px 0 0}.popular-posts{margin:0;padding:1em 0;text-align:left}.popular-posts .popular-posts-item{display:block}.popular-posts .popular-posts-item .popular-posts-link{border-bottom:0;display:block;padding:5px 20px;transition:background .2s ease-in-out}.popular-posts .popular-posts-item .popular-posts-link:hover{background:var(--menu-item-bg-color)}.popular-posts .popular-posts-item .popular-posts-time{color:#999}.footer{color:#999;font-size:.875em;padding:20px 0}.footer.footer-fixed{bottom:0;left:0;position:absolute;right:0}.footer-inner{box-sizing:border-box;text-align:center;display:flex;flex-direction:column;justify-content:center;margin:0 auto;width:calc(100% - 20px)}@media (max-width:767px){.menu-item .badge{float:right;margin-left:0}.footer-inner{width:auto}}@media (min-width:1200px){.footer-inner{width:1160px}}@media (min-width:1600px){.footer-inner{width:73%}}.use-motion .footer{opacity:0}.languages{display:inline-block;font-size:1.125em;position:relative}.languages .lang-select-label span{margin:0 .5em}.languages .lang-select{height:100%;left:0;opacity:0;position:absolute;top:0;width:100%}.with-love{color:red;display:inline-block;margin:0 5px}.beian img{display:inline-block;margin:0 3px;vertical-align:middle}.busuanzi-count #busuanzi_container_site_pv,.busuanzi-count #busuanzi_container_site_uv{display:none}@keyframes icon-animate{0%,100%{transform:scale(1)}10%,30%{transform:scale(.9)}20%,40%,50%,60%,70%,80%{transform:scale(1.1)}}@media (max-width:567px){.main-inner{padding:initial!important}.posts-expand .post-header{margin-bottom:10px!important}.post-block{margin-top:initial!important;padding:8px 18px!important}.post-body h1,.post-body h2,.post-body h3,.post-body h4,.post-body h5,.post-body h6{margin:20px 0 8px}.post-body .note h1,.post-body .note h2,.post-body .note h3,.post-body .note h4,.post-body .note h5,.post-body .note h6,.post-body .tabs .tab-content .tab-pane h1,.post-body .tabs .tab-content .tab-pane h2,.post-body .tabs .tab-content .tab-pane h3,.post-body .tabs .tab-content .tab-pane h4,.post-body .tabs .tab-content .tab-pane h5,.post-body .tabs .tab-content .tab-pane h6{margin:0 5px}.post-body>p{margin:0 0 10px}.post-body .note>p,.post-body .tabs .tab-content .tab-pane>p{padding:0 5px}.post-body img,.post-body video{margin-bottom:10px!important}.post-body .note{margin-bottom:10px!important;padding:10px!important}.post-body .tabs .tab-content .tab-pane{padding:10px 10px 0!important}.post-eof{margin:40px auto 20px!important}.pagination{margin-top:40px}}.back-to-top{font-size:12px;align-items:center;bottom:-100px;color:#fff;display:flex;height:26px;transition:bottom .2s ease-in-out;background:#222;cursor:pointer;opacity:.6;position:fixed;z-index:30;right:30px}.back-to-top span{margin-right:8px;display:none}.back-to-top .fa{text-align:center;width:26px}.back-to-top:hover{opacity:.8;color:#fc6423}.back-to-top.back-to-top-on{bottom:30px}.rtl.post-body a,.rtl.post-body h1,.rtl.post-body h2,.rtl.post-body h3,.rtl.post-body h4,.rtl.post-body h5,.rtl.post-body h6,.rtl.post-body li,.rtl.post-body ol,.rtl.post-body p,.rtl.post-body ul{direction:rtl;font-family:UKIJ Ekran}.rtl.post-title{font-family:UKIJ Ekran}.post-button{margin-top:40px;text-align:center}.use-motion .collection-header,.use-motion .comments,.use-motion .pagination,.use-motion .post-block,.use-motion .post-body,.use-motion .post-header{visibility:hidden}.posts-collapse .post-content{margin-bottom:35px;margin-left:35px;position:relative}@media (max-width:767px){.posts-collapse .post-content{margin-left:0;margin-right:0}}.posts-collapse .post-content .collection-title{font-size:1.125em;position:relative}.posts-collapse .post-content .collection-title::before{background:#999;border:1px solid #fff;margin-left:-6px;margin-top:-4px;position:absolute;top:50%;border-radius:50%;content:' ';height:10px;width:10px}.posts-collapse .post-content .collection-year{font-size:1.5em;font-weight:700;margin:60px 0;position:relative}.posts-collapse .post-content .collection-year::before{background:#bbb;margin-left:-4px;margin-top:-4px;position:absolute;top:50%;border-radius:50%;content:' ';height:8px;width:8px}.posts-collapse .post-content .collection-header{display:block;margin-left:20px}.posts-collapse .post-content .collection-header small{color:#bbb;margin-left:5px}.posts-collapse .post-content .post-header{border-bottom:1px dashed #ccc;margin:30px 2px 0;padding-left:15px;position:relative;transition:border .2s ease-in-out}.posts-collapse .post-content .post-header::before{background:#bbb;border:1px solid #fff;left:-6px;position:absolute;top:.75em;transition:background .2s ease-in-out;border-radius:50%;content:' ';height:6px;width:6px}.posts-collapse .post-content .post-header:hover{border-bottom-color:#666}.posts-collapse .post-content .post-header:hover::before{background:#222}.posts-collapse .post-content .post-meta-container{display:inline;font-size:.75em;margin-right:10px}.posts-collapse .post-content .post-title{display:inline}.posts-collapse .post-content .post-title a{border-bottom:0;color:var(--link-color)}.posts-collapse .post-content .post-title .fa-external-link-alt{font-size:.875em;margin-left:5px}.posts-collapse .post-content::before{background:#f5f5f5;content:' ';height:100%;margin-left:-2px;position:absolute;top:1.25em;width:4px}.post-body{font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;overflow-wrap:break-word}@media (min-width:1200px){.post-body{font-size:1.125em}}@media (min-width:992px){.post-body{text-align:justify}}.post-body h1 .header-anchor,.post-body h1 .headerlink,.post-body h2 .header-anchor,.post-body h2 .headerlink,.post-body h3 .header-anchor,.post-body h3 .headerlink,.post-body h4 .header-anchor,.post-body h4 .headerlink,.post-body h5 .header-anchor,.post-body h5 .headerlink,.post-body h6 .header-anchor,.post-body h6 .headerlink{border-bottom-style:none;color:inherit;float:right;font-size:.875em;margin-left:10px;opacity:0}.post-body h1 .header-anchor::before,.post-body h1 .headerlink::before,.post-body h2 .header-anchor::before,.post-body h2 .headerlink::before,.post-body h3 .header-anchor::before,.post-body h3 .headerlink::before,.post-body h4 .header-anchor::before,.post-body h4 .headerlink::before,.post-body h5 .header-anchor::before,.post-body h5 .headerlink::before,.post-body h6 .header-anchor::before,.post-body h6 .headerlink::before{content:'\f0c1';font-family:'Font Awesome 6 Free';font-weight:900}.post-body h1:hover .header-anchor,.post-body h1:hover .headerlink,.post-body h2:hover .header-anchor,.post-body h2:hover .headerlink,.post-body h3:hover .header-anchor,.post-body h3:hover .headerlink,.post-body h4:hover .header-anchor,.post-body h4:hover .headerlink,.post-body h5:hover .header-anchor,.post-body h5:hover .headerlink,.post-body h6:hover .header-anchor,.post-body h6:hover .headerlink{opacity:.5}.post-body h1:hover .header-anchor:hover,.post-body h1:hover .headerlink:hover,.post-body h2:hover .header-anchor:hover,.post-body h2:hover .headerlink:hover,.post-body h3:hover .header-anchor:hover,.post-body h3:hover .headerlink:hover,.post-body h4:hover .header-anchor:hover,.post-body h4:hover .headerlink:hover,.post-body h5:hover .header-anchor:hover,.post-body h5:hover .headerlink:hover,.post-body h6:hover .header-anchor:hover,.post-body h6:hover .headerlink:hover{opacity:1}.post-body .exturl .fa{font-size:.875em;margin-left:4px}.post-body .fancybox+figcaption,.post-body .image-caption,.post-body img+figcaption{color:#999;font-size:.875em;font-weight:700;line-height:1;margin:-15px auto 15px;text-align:center}.post-body embed,.post-body iframe,.post-body img,.post-body video{margin-bottom:20px}.post-body .video-container{height:0;margin-bottom:20px;overflow:hidden;padding-top:75%;position:relative;width:100%}.post-body .video-container embed,.post-body .video-container iframe,.post-body .video-container object{height:100%;left:0;margin:0;position:absolute;top:0;width:100%}.post-gallery{display:flex;min-height:200px}.post-gallery .post-gallery-image{flex:1}.post-gallery .post-gallery-image:not(:first-child){clip-path:polygon(40px 0,100% 0,100% 100%,0 100%);margin-left:-20px}.post-gallery .post-gallery-image:not(:last-child){margin-right:-20px}.post-gallery .post-gallery-image img{height:100%;object-fit:cover;opacity:1;width:100%}.posts-expand .post-gallery{margin-bottom:60px}.posts-collapse .post-gallery{margin:15px 0}.posts-expand .post-header{font-size:1.125em;margin-bottom:60px;text-align:center}.posts-expand .post-title{font-size:1.5em;font-weight:400;margin:initial;overflow-wrap:break-word}.posts-expand .post-title-link{border-bottom:0;color:var(--link-color);display:inline-block;position:relative}.posts-expand .post-title-link::before{background:var(--link-color);bottom:0;content:'';height:2px;left:0;position:absolute;transform:scaleX(0);transition:transform .2s ease-in-out;width:100%}.posts-expand .post-title-link:hover::before{transform:scaleX(1)}.posts-expand .post-title-link .fa-external-link-alt{font-size:.875em;margin-left:5px}.post-sticky-flag{display:inline-block;margin-right:8px;transform:rotate(30deg)}.posts-expand .post-meta-container{color:#999;font-family:Lato,'PingFang SC','Microsoft YaHei',sans-serif;font-size:.75em;margin-top:3px}.posts-expand .post-meta-container .post-description{font-size:.875em;margin-top:2px}.posts-expand .post-meta-container time{border-bottom:1px dashed #999}.post-meta{display:flex;flex-wrap:wrap;justify-content:center}:not(.post-meta-break)+.post-meta-item::before{content:'|';margin:0 .5em}.post-meta-item-icon{margin-right:3px}@media (max-width:991px){.back-to-top{right:20px;opacity:.8}.post-body{text-align:justify}.post-meta-item-text{display:none}}.post-meta-break{flex-basis:100%;height:0}#busuanzi_container_page_pv{display:none}.post-nav{border-top:1px solid #eee;display:flex;gap:30px;justify-content:space-between;margin-top:1em;padding:10px 5px 0}.post-nav-item{flex:1}.post-nav-item a{border-bottom:0;display:block;font-size:.875em;line-height:1.6}.post-nav-item a:active{top:2px}.post-nav-item .fa{font-size:.75em}.post-nav-item:first-child .fa{margin-right:5px}.post-nav-item:last-child{text-align:right}.post-nav-item:last-child .fa{margin-left:5px}.post-footer{display:flex;flex-direction:column;justify-content:center}.post-eof{background:#ccc;height:1px;margin:80px auto 60px;width:8%}.post-block:last-of-type .post-eof{display:none}.post-copyright ul{list-style:none;overflow:hidden;padding:.5em 1em;position:relative;background:var(--card-bg-color);border-left:3px solid #ff2a2a;margin:1em 0 0}.post-copyright ul::after{content:'\f25e';font-family:'Font Awesome 6 Brands';font-size:200px;opacity:.1;position:absolute;right:-50px;top:-150px}.post-tags{margin-top:40px;text-align:center}.post-tags a{display:inline-block;font-size:.8125em}.post-tags a:not(:last-child){margin-right:10px}.social-like{border-top:1px solid #eee;font-size:.875em;margin-top:1em;padding-top:1em;text-align:center}.reward-container{margin:1em 0 0;padding:1em 0;text-align:center}.reward-container button{background:0 0;color:#fc6423;cursor:pointer;line-height:2;padding:0 15px;border:2px solid #fc6423;border-radius:2px;outline:0;transition:.2s ease-in-out;vertical-align:text-top}.reward-container button:hover{background:#fc6423;color:#fff}.post-reward{display:none;padding-top:20px}.post-reward.active{display:block}.post-reward div{display:inline-block}.post-reward div span{display:block}.post-reward img{display:inline-block;margin:.8em 2em 0;max-width:100%;width:180px}@keyframes next-roll{from{transform:rotateZ(30deg)}to{transform:rotateZ(-30deg)}}.category-all-page .category-all-title{text-align:center}.category-all-page .category-all{margin-top:20px}.category-all-page .category-list{list-style:none;margin:0;padding:0}.category-all-page .category-list-item{margin:5px 10px}.category-all-page .category-list-count{color:#bbb}.category-all-page .category-list-count::before{content:' ('}.category-all-page .category-list-count::after{content:') '}.category-all-page .category-list-child{padding-left:10px}.event-list hr{background:#222;margin:20px 0 45px}.event-list hr::after{background:#222;color:#fff;content:'NOW';display:inline-block;font-weight:700;padding:0 5px}.event-list .event{--event-background:#222;--event-foreground:#bbb;--event-title:#fff;background:var(--event-background);padding:15px}.event-list .event .event-summary{border-bottom:0;color:var(--event-title);margin:0;padding:0 0 0 35px;position:relative}.event-list .event .event-summary::before{animation:1s ease-in-out infinite alternate dot-flash;background:var(--event-title);left:0;margin-top:-6px;position:absolute;top:50%;border-radius:50%;content:' ';height:12px;width:12px}.event-list .event:nth-of-type(odd) .event-summary::before{animation-delay:.5s}.event-list .event:not(:last-child){margin-bottom:20px}.event-list .event .event-relative-time{color:var(--event-foreground);display:inline-block;font-size:12px;font-weight:400;padding-left:12px}.event-list .event .event-details{color:var(--event-foreground);display:block;line-height:18px;padding:6px 0 6px 35px}.event-list .event .event-details::before{color:var(--event-foreground);display:inline-block;margin-right:9px;width:14px;font-family:'Font Awesome 6 Free';font-weight:900}.event-list .event .event-details.event-location::before{content:'\f041'}.event-list .event .event-details.event-duration::before{content:'\f017'}.event-list .event .event-details.event-description::before{content:'\f024'}.event-list .event-past{--event-background:#f5f5f5;--event-foreground:#999;--event-title:#222}@keyframes dot-flash{from{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.8)}}ul.breadcrumb{font-size:.75em;list-style:none;margin:1em 0;padding:0 2em;text-align:center}ul.breadcrumb li{display:inline}ul.breadcrumb li:not(:first-child)::before{content:'/\00a0';font-weight:400;padding:.5em}ul.breadcrumb li:last-child{font-weight:700}.tag-cloud{text-align:center}.tag-cloud a{display:inline-block;margin:10px}.tag-cloud-0{border-bottom-color:#aaa;color:#aaa}.tag-cloud-1{border-bottom-color:#9a9a9a;color:#9a9a9a}.tag-cloud-2{border-bottom-color:#8b8b8b;color:#8b8b8b}.tag-cloud-3{border-bottom-color:#7c7c7c;color:#7c7c7c}.tag-cloud-4{border-bottom-color:#6c6c6c;color:#6c6c6c}.tag-cloud-5{border-bottom-color:#5d5d5d;color:#5d5d5d}.tag-cloud-6{border-bottom-color:#4e4e4e;color:#4e4e4e}.tag-cloud-7{border-bottom-color:#3e3e3e;color:#3e3e3e}.tag-cloud-8{border-bottom-color:#2f2f2f;color:#2f2f2f}.tag-cloud-9{border-bottom-color:#202020;color:#202020}.tag-cloud-10{border-bottom-color:#111;color:#111}.search-active{overflow:hidden}.search-pop-overlay{background:rgba(0,0,0,0);display:flex;height:100%;left:0;position:fixed;top:0;transition:visibility .4s,background .4s;visibility:hidden;width:100%;z-index:40}.search-active .search-pop-overlay{background:rgba(0,0,0,.3);visibility:visible}.search-popup{background:var(--card-bg-color);border-radius:5px;height:80%;margin:auto;transform:scale(0);transition:transform .4s;width:700px}.search-active .search-popup{transform:scale(1)}@media (max-width:767px){.search-popup{border-radius:0;height:100%;width:100%}}.search-popup .popup-btn-close,.search-popup .search-icon{color:#999;font-size:18px;padding:0 10px}.search-popup .popup-btn-close{cursor:pointer}.search-popup .popup-btn-close:hover .fa{color:#222}.search-popup .search-header{background:#eee;border-top-left-radius:5px;border-top-right-radius:5px;display:flex;padding:5px}.search-popup input.search-input{background:0 0;border:0;outline:0;width:100%}.search-popup input.search-input::-webkit-search-cancel-button{display:none}.search-popup .search-result-container{height:calc(100% - 55px);overflow:auto;padding:5px 25px}.search-popup .search-result-container hr{margin:5px 0 10px}.search-popup .search-result-container hr:first-child{display:none}.search-popup .search-result-list{margin:0 5px;padding:0}.search-popup a.search-result-title{font-weight:700}.search-popup p.search-result{border-bottom:1px dashed #ccc;padding:5px 0}.search-input-container{flex-grow:1}.search-input-container form{padding:2px}.search-stats{align-items:center;display:flex;justify-content:space-between}.search-stats img{height:1em;margin:0}.algolia-pagination{margin:40px 0;opacity:1;padding:0}.algolia-pagination .pagination-item{display:inline-block}.algolia-pagination .current .page-number{cursor:default}.algolia-pagination .disabled-item{visibility:hidden}.use-motion .animated{animation-fill-mode:none;visibility:inherit}.use-motion .sidebar .animated{animation-fill-mode:both}.header{background:var(--content-bg-color);border-radius:initial;box-shadow:initial}.main{align-items:stretch;display:flex;justify-content:space-between;margin:0 auto;width:calc(100% - 20px)}@media (max-width:767px){.main{width:auto}}@media (min-width:1200px){.main{width:1160px}}@media (min-width:1600px){.main{width:73%}}@media (max-width:991px){.header{border-radius:initial}.main{display:block;width:auto}}.main-inner{border-radius:initial;box-sizing:border-box;width:calc(100% - 252px)}.footer-inner{padding-left:252px}@media (max-width:991px){.main-inner{border-radius:initial;width:100%}.footer-inner{padding-left:0;padding-right:0;width:auto}}.column{width:240px}.site-brand-container{background:var(--theme-color)}.site-meta{padding:20px 0}.site-nav-right .toggle,.site-nav-toggle .toggle{color:#fff}.site-nav-right .toggle .toggle-line,.site-nav-toggle .toggle .toggle-line{background:#fff}@media (min-width:768px) and (max-width:991px){.site-nav-right,.site-nav-toggle{display:flex;flex-direction:column;justify-content:center}.site-nav{--scroll-height:0;height:0;overflow:hidden;transition:height .2s ease-in-out}body:not(.site-nav-on) .site-nav .animated{animation:none}body.site-nav-on .site-nav{height:var(--scroll-height)}}.menu .menu-item{display:block;margin:0}.menu .menu-item a{padding:5px 20px;position:relative;text-align:left;transition-property:background-color}.menu .menu-item .badge{background:#ccc;border-radius:10px;color:var(--content-bg-color);float:right;padding:2px 5px;text-shadow:1px 1px 0 rgba(0,0,0,.1)}.main-menu .menu-item-active::after{background:#bbb;border-radius:50%;content:' ';height:6px;margin-top:-3px;position:absolute;right:15px;top:50%;width:6px}.sub-menu{margin:0;padding:6px 0}.sub-menu .menu-item{display:inline-block}.sub-menu .menu-item a{background:0 0;margin:5px 10px;padding:initial}.sub-menu .menu-item a:hover{background:0 0;color:#fc6423}.sub-menu .menu-item-active{border-bottom-color:#fc6423;color:#fc6423}.sub-menu .menu-item-active:hover{border-bottom-color:#fc6423}.sidebar{position:-webkit-sticky;position:sticky;top:12px}@media (max-width:991px){.column{width:auto}.site-nav-on .site-brand-container{box-shadow:0 0 16px rgba(0,0,0,.5)}.menu .menu-item.menu-item-search,.sidebar{display:none}}.sidebar-inner{background:var(--content-bg-color);border-radius:initial;box-shadow:initial;box-sizing:border-box;color:var(--text-color);margin-top:12px;max-height:calc(100vh - 24px);visibility:hidden}.site-state-item{padding:0 10px}.sidebar .sidebar-button{border-bottom:1px dotted #ccc;border-top:1px dotted #ccc}.sidebar .sidebar-button button{border:0;color:#fc6423;display:block;width:100%}.sidebar .sidebar-button button:hover{background:0 0;border:0;color:#e34603}.links-of-author{display:flex;flex-wrap:wrap;justify-content:center}.links-of-author-item{margin:5px 0 0;width:50%}.links-of-author-item a{box-sizing:border-box;max-width:100%;overflow:hidden;padding:0 5px;text-overflow:ellipsis;white-space:nowrap;border-bottom:0;border-radius:4px;display:block}.links-of-author-item a:hover{background:var(--body-bg-color)}.main-inner{background:var(--content-bg-color);box-shadow:initial;padding:40px}@media (max-width:991px){.main-inner{padding:20px}}.sub-menu{border-bottom:1px solid #ddd}.post-block:first-of-type{padding-top:40px}@media (max-width:767px){.pagination{margin-bottom:10px}}</style><link as=style href=https://fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&display=swap&subset=latin,latin-ext onload=this.rel='stylesheet' rel=preload><link crossorigin=anonymous href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css integrity=sha256-Z1K5uhUaJXA7Ll0XrZ/0JhX4lAtZFpT6jkKrEDT0drU= rel=stylesheet><link crossorigin=anonymous href=https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css integrity=sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE= rel=stylesheet><link crossorigin=anonymous href=https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css integrity=sha256-Vzbj7sDDS/woiFS3uNKo8eIuni59rjyNGtXfstRzStA= rel=stylesheet><script class=next-config data-name=main type=application/json>{"hostname":"nicksxs.me","root":"/","images":"/images","scheme":"Pisces","darkmode":false,"version":"8.14.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果:${query}","hits_time":"找到 ${hits} 个搜索结果(用时 ${time} 毫秒)","hits":"找到 ${hits} 个搜索结果"},"algolia":{"appID":"663Q99OQQD","apiKey":"e461a1371d12cec1491c1153b288a9ed","indexName":"nicksxs","hits":{"per_page":10}}}</script><script src=/js/config.js></script><meta content="Condition也是 AQS 中很重要的一块内容,可以先看段示例代码,这段代码应该来自于Doug Lea大大,可以在 javadoc 中的 condition 部分找到,其实大大原来写过基于 synchronized 实现的,后面我也贴下代码 import java.util.concurrent.locks.Condition; import java.util.concurrent.lock" name=description><meta content=article property=og:type><meta content="AQS篇二 之 Condition 浅析笔记" property=og:title><meta content=https://nicksxs.me/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/index.html property=og:url><meta content="Nicksxs's Blog" property=og:site_name><meta content="Condition也是 AQS 中很重要的一块内容,可以先看段示例代码,这段代码应该来自于Doug Lea大大,可以在 javadoc 中的 condition 部分找到,其实大大原来写过基于 synchronized 实现的,后面我也贴下代码 import java.util.concurrent.locks.Condition; import java.util.concurrent.lock" property=og:description><meta content=zh_CN property=og:locale><meta content=https://img.nicksxs.com/uPic/Ss9oFX.png property=og:image><meta content=2021-02-21T13:27:06.000Z property=article:published_time><meta content=2022-06-11T14:45:11.000Z property=article:modified_time><meta content=Nicksxs property=article:author><meta content=java property=article:tag><meta content=并发 property=article:tag><meta content=j.u.c property=article:tag><meta content=aqs property=article:tag><meta content=condition property=article:tag><meta content=await property=article:tag><meta content=signal property=article:tag><meta content=lock property=article:tag><meta content=unlock property=article:tag><meta content=summary name=twitter:card><meta content=https://img.nicksxs.com/uPic/Ss9oFX.png name=twitter:image><link href=https://nicksxs.me/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/ rel=canonical><script class=next-config data-name=page type=application/json>{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://nicksxs.me/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/","path":"2021/02/21/AQS-之-Condition-浅析笔记/","title":"AQS篇二 之 Condition 浅析笔记"}</script><script class=next-config data-name=calendar type=application/json>""</script><title>AQS篇二 之 Condition 浅析笔记 | Nicksxs's Blog</title><script async src=https://www.googletagmanager.com/gtag/js?id=UA-61358619-1></script><script class=next-config data-name=google_analytics type=application/json>{"tracking_id":"UA-61358619-1","only_pageview":false}</script><script src=/js/third-party/analytics/google-analytics.js></script><script src=/js/third-party/analytics/baidu-analytics.js></script><script async src=https://hm.baidu.com/hm.js?20f33b3c0c0eff9b1522999c0015646d></script><noscript><link href=/css/noscript.css rel=stylesheet></noscript><link title="Nicksxs's Blog" href=/atom.xml rel=alternate type=application/atom+xml><body class=use-motion itemscope itemtype=http://schema.org/WebPage><div class=headband></div><main class=main><div class=column><header class=header itemscope itemtype=http://schema.org/WPHeader><div class=site-brand-container><div class=site-nav-toggle><div aria-label=切换导航栏 class=toggle role=button><span class=toggle-line></span><span class=toggle-line></span><span class=toggle-line></span></div></div><div class=site-meta><a class=brand href=/ rel=start><i class=logo-line></i><p class=site-title>Nicksxs's Blog</p><i class=logo-line></i></a><p class=site-subtitle itemprop=description>What hurts more, the pain of hard work or the pain of regret?</div><div class=site-nav-right><div class="toggle popup-trigger" aria-label=搜索 role=button><i class="fa fa-search fa-fw fa-lg"></i></div></div></div><nav class=site-nav><ul class="main-menu menu"><li class="menu-item menu-item-home"><a href=/ rel=section><i class="fa fa-home fa-fw"></i>首页</a><li class="menu-item menu-item-about"><a href=/about/ rel=section><i class="fa fa-user fa-fw"></i>关于</a><li class="menu-item menu-item-tags"><a href=/tags/ rel=section><i class="fa fa-tags fa-fw"></i>标签</a><li class="menu-item menu-item-categories"><a href=/categories/ rel=section><i class="fa fa-th fa-fw"></i>分类</a><li class="menu-item menu-item-archives"><a href=/archives/ rel=section><i class="fa fa-archive fa-fw"></i>归档</a><li class="menu-item menu-item-top"><a href=/top/ rel=section><i class="fa fa-th fa-fw"></i>热度</a><li class="menu-item menu-item-sitemap"><a href=/sitemap.xml rel=section><i class="fa fa-sitemap fa-fw"></i>站点地图</a><li class="menu-item menu-item-commonweal"><a href=/404/ rel=section><i class="fa fa-heartbeat fa-fw"></i>公益 404</a><li class="menu-item menu-item-search"><a class=popup-trigger role=button><i class="fa fa-search fa-fw"></i>搜索</a></ul></nav><div class=search-pop-overlay><div class="popup search-popup"><div class=search-header><span class=search-icon><i class="fa fa-search"></i></span><div class=search-input-container></div><span class=popup-btn-close role=button><i class="fa fa-times-circle"></i></span></div><div class=search-result-container><div class=algolia-stats><hr></div><div class=algolia-hits></div><div class=algolia-pagination></div></div></div></div></header><aside class=sidebar><div class="sidebar-inner sidebar-nav-active sidebar-toc-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 class="post-toc animated"><ol class=nav><li class="nav-item nav-level-2"><a class=nav-link href=#signal><span class=nav-number>1.</span> <span class=nav-text>signal</span></a><li class="nav-item nav-level-2"><a class=nav-link href=#%E9%99%84%E5%BD%95><span class=nav-number>2.</span> <span class=nav-text>附录</span></a></ol></div></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>205</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>151</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>289</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>43</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>12</span><li class=tag-list-item><a class=tag-list-link href=/tags/Mysql/ rel=tag>Mysql</a><span class=tag-list-count>12</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>6</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>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/Sql%E6%B3%A8%E5%85%A5/ rel=tag>Sql注入</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Stream/ rel=tag>Stream</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Synchronized/ rel=tag>Synchronized</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/Thread-dump/ rel=tag>Thread dump</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/ThreadLocal/ rel=tag>ThreadLocal</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/ThreadPool/ rel=tag>ThreadPool</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Tomcat/ rel=tag>Tomcat</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Trapping-Rain-Water/ rel=tag>Trapping Rain Water</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/WeakReference/ rel=tag>WeakReference</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Web/ rel=tag>Web</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Webhook/ rel=tag>Webhook</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/Windows/ rel=tag>Windows</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/WordPress/ rel=tag>WordPress</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/aqs/ rel=tag>aqs</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/await/ rel=tag>await</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/bloom-filter/ rel=tag>bloom filter</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/c/ rel=tag>c++</a><span class=tag-list-count>14</span><li class=tag-list-item><a class=tag-list-link href=/tags/cglib/ rel=tag>cglib</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/cgroup/ rel=tag>cgroup</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/cluster/ rel=tag>cluster</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/condition/ rel=tag>condition</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/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>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>33</span><li class=tag-list-item><a class=tag-list-link href=/tags/jvm/ rel=tag>jvm</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/leetcode/ rel=tag>leetcode</a><span class=tag-list-count>40</span><li class=tag-list-item><a class=tag-list-link href=/tags/leetcode-155/ rel=tag>leetcode 155</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/linked-list/ rel=tag>linked list</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/linux/ rel=tag>linux</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/lock/ rel=tag>lock</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/mfc/ rel=tag>mfc</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/min-stack/ rel=tag>min stack</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/mq/ rel=tag>mq</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/mvcc/ rel=tag>mvcc</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/mysql/ rel=tag>mysql</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/namespace/ rel=tag>namespace</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/next-key-lock/ rel=tag>next-key lock</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/nginx/ rel=tag>nginx</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/nullsfirst/ rel=tag>nullsfirst</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/openresty/ rel=tag>openresty</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/php/ rel=tag>php</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/powershell/ rel=tag>powershell</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/procedure/ rel=tag>procedure</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/python/ rel=tag>python</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/read-view/ rel=tag>read view</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/redis/ rel=tag>redis</a><span class=tag-list-count>12</span><li class=tag-list-item><a class=tag-list-link href=/tags/scp/ rel=tag>scp</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/signal/ rel=tag>signal</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/sort/ rel=tag>sort</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/spark/ rel=tag>spark</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/ssh/ rel=tag>ssh</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/stack/ rel=tag>stack</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/stream/ rel=tag>stream</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/string/ rel=tag>string</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/swoole/ rel=tag>swoole</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/top/ rel=tag>top</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/uname/ rel=tag>uname</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/unlock/ rel=tag>unlock</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8/ rel=tag>utf8</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4/ rel=tag>utf8mb4</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4-0900-ai-ci/ rel=tag>utf8mb4_0900_ai_ci</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4-general-ci/ rel=tag>utf8mb4_general_ci</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/utf8mb4-unicode-ci/ rel=tag>utf8mb4_unicode_ci</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/value/ rel=tag>value</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/websocket/ rel=tag>websocket</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/zookeeper/ rel=tag>zookeeper</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/zsh/ rel=tag>zsh</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ rel=tag>三阶段提交</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%8D%E5%8F%AF%E5%8F%98%E5%BC%95%E7%94%A8/ rel=tag>不可变引用</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%9C%E4%BA%AC%E5%A5%A5%E8%BF%90%E4%BC%9A/ rel=tag>东京奥运会</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ rel=tag>两阶段提交</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%AD%E5%B1%B1%E8%B7%AF/ rel=tag>中山路</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%AD%E5%BA%8F/ rel=tag>中序</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%AD%E9%97%B4%E4%BB%B6/ rel=tag>中间件</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B8%BE%E9%87%8D/ rel=tag>举重</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%B9%92%E4%B9%93%E7%90%83/ rel=tag>乒乓球</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BA%8B%E5%8A%A1/ rel=tag>事务</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BA%8C%E5%8F%89%E6%A0%91/ rel=tag>二叉树</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BA%92%E6%96%A5%E9%94%81/ rel=tag>互斥锁</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BB%A3%E7%A0%81%E9%A2%98%E8%A7%A3/ rel=tag>代码题解</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E4%BF%AE%E7%94%B5%E8%84%91%E7%9A%84/ rel=tag>修电脑的</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%81%8F%E5%90%91%E9%94%81/ rel=tag>偏向锁</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%81%A5%E5%BA%B7%E7%A0%81/ rel=tag>健康码</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%85%AC%E4%BA%A4/ rel=tag>公交</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%85%AC%E4%BA%A4%E8%BD%A6/ rel=tag>公交车</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%86%85%E5%AD%98%E5%88%86%E5%B8%83/ rel=tag>内存分布</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/ rel=tag>内存泄漏</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%87%86%E5%A4%87/ rel=tag>准备</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%87%8F%E8%82%A5/ rel=tag>减肥</a><span class=tag-list-count>7</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ rel=tag>分布式事务</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/ rel=tag>分布式锁</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%87%E7%89%87/ rel=tag>切片</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%88%9D%E5%A7%8B%E5%8C%96/ rel=tag>初始化</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%89%8A%E5%B3%B0%E5%A1%AB%E8%B0%B7/ rel=tag>削峰填谷</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%89%8D%E5%BA%8F/ rel=tag>前序</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8A%A0%E5%A1%9E/ rel=tag>加塞</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8A%A0%E8%BD%BD/ rel=tag>加载</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8D%95%E4%BE%8B/ rel=tag>单例</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8D%9A%E5%AE%A2%EF%BC%8C%E6%96%87%E7%AB%A0/ rel=tag>博客,文章</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8E%A6%E9%97%A8/ rel=tag>厦门</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE/ rel=tag>双亲委派</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%91%E8%A1%8C%E7%89%88/ rel=tag>发行版</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%A3%E7%BD%A9/ rel=tag>口罩</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%8F%AF%E5%8F%98%E5%BC%95%E7%94%A8/ rel=tag>可变引用</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%90%90%E6%A7%BD/ rel=tag>吐槽</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%9B%A4%E7%89%A9%E8%B5%84/ rel=tag>囤物资</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6/ rel=tag>垃圾回收</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%9F%BA%E7%A1%80%E8%AE%BE%E6%96%BD/ rel=tag>基础设施</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%A4%A7%E6%89%AB%E9%99%A4/ rel=tag>大扫除</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AD%97%E7%AC%A6%E9%9B%86/ rel=tag>字符集</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AE%89%E5%85%A8/ rel=tag>安全</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B6/ rel=tag>容错机制</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%AF%84%E7%94%9F%E8%99%AB/ rel=tag>寄生虫</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B0%84%E5%87%BB/ rel=tag>射击</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B0%8F%E6%8A%80%E5%B7%A7/ rel=tag>小技巧</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B1%80%E5%8F%A3%E8%A1%97/ rel=tag>局口街</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8/ rel=tag>布隆过滤器</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B2%E6%B4%BB/ rel=tag>干活</a><span class=tag-list-count>6</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/ rel=tag>年中总结</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ rel=tag>年终总结</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B6%E5%8F%91/ rel=tag>并发</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%B8%E7%A6%8F%E4%BA%86%E5%90%97/ rel=tag>幸福了吗</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%B9%BB%E8%AF%BB/ rel=tag>幻读</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BA%94%E7%94%A8/ rel=tag>应用</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BC%80%E8%BD%A6/ rel=tag>开车</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BC%B1%E5%BC%95%E7%94%A8/ rel=tag>弱引用</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E5%BD%B1%E8%AF%84/ rel=tag>影评</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%89%80%E6%9C%89%E6%9D%83/ rel=tag>所有权</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%89%93%E5%8D%A1/ rel=tag>打卡</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%89%B6%E6%A2%AF/ rel=tag>扶梯</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8A%80%E6%9C%AF/ rel=tag>技术</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8B%96%E6%9B%B4/ rel=tag>拖更</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8D%A2%E8%BD%A6%E7%89%8C/ rel=tag>换车牌</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8E%92%E5%BA%8F/ rel=tag>排序</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%8E%A5%E9%9B%A8%E6%B0%B4/ rel=tag>接雨水</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%95%B0%E6%8D%AE%E6%BA%90%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2/ rel=tag>数据源动态切换</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ rel=tag>数据结构</a><span class=tag-list-count>11</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%96%B0%E8%AF%AD%E8%A8%80/ rel=tag>新语言</a><span class=tag-list-count>3</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%97%85%E6%B8%B8/ rel=tag>旅游</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%97%A5%E5%BF%97/ rel=tag>日志</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9B%BE%E5%8E%9D%E5%9E%B5/ rel=tag>曾厝垵</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9C%80%E5%B0%8F%E6%A0%88/ rel=tag>最小栈</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9D%80%E4%BA%BA%E8%AF%9B%E5%BF%83/ rel=tag>杀人诛心</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%9D%AD%E5%B7%9E/ rel=tag>杭州</a><span class=tag-list-count>4</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%A0%87%E8%AE%B0%E6%95%B4%E7%90%86/ rel=tag>标记整理</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%A4%8D%E7%89%A9%E5%9B%AD/ rel=tag>植物园</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B2%99%E8%8C%B6%E9%9D%A2/ rel=tag>沙茶面</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B3%A8%E8%A7%A3/ rel=tag>注解</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B5%B7%E8%9B%8E%E7%85%8E/ rel=tag>海蛎煎</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/ rel=tag>消息队列</a><span class=tag-list-count>9</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%B7%98%E6%B1%B0%E7%AD%96%E7%95%A5/ rel=tag>淘汰策略</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E6%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>3</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%B3%E6%B0%B4/ rel=tag>跳水</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%B8%A9%E8%B8%8F/ rel=tag>踩踏</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BD%AC%E4%B9%89/ rel=tag>转义</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BD%BB%E9%87%8F%E7%BA%A7%E9%94%81/ rel=tag>轻量级锁</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BF%87%E6%9C%9F%E7%AD%96%E7%95%A5/ rel=tag>过期策略</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BF%90%E5%8A%A8/ rel=tag>运动</a><span class=tag-list-count>9</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E8%BF%9C%E7%A8%8B%E5%8A%9E%E5%85%AC/ rel=tag>远程办公</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%80%92%E5%BD%92/ rel=tag>递归</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%87%8D%E9%87%8F%E7%BA%A7%E9%94%81/ rel=tag>重量级锁</a><span class=tag-list-count>2</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%93%BE%E6%8E%A5/ rel=tag>链接</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%A2%98%E8%A7%A3/ rel=tag>题解</a><span class=tag-list-count>24</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%A9%AC%E6%88%8F%E5%9B%A2/ rel=tag>马戏团</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%AA%8C%E8%AF%81/ rel=tag>验证</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%AA%91%E8%BD%A6/ rel=tag>骑车</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%AB%98%E9%80%9F/ rel=tag>高速</a><span class=tag-list-count>1</span><li class=tag-list-item><a class=tag-list-link href=/tags/%E9%BC%93%E6%B5%AA%E5%B1%BF/ rel=tag>鼓浪屿</a><span class=tag-list-count>1</span></ul></canvas></div></div></div></div></div><div class="sidebar-inner sidebar-blogroll"><div class="links-of-blogroll animated"><div class=links-of-blogroll-title><i class="fa fa-globe fa-fw"></i> 链接</div><ul class=links-of-blogroll-list><li class=links-of-blogroll-item><a href=https://covermusic.cn/ rel=noopener target=_blank title=https://covermusic.cn>69伙伴</a></ul></div></div></aside></div><div class="main-inner post posts-expand"><div class=post-block><article class=post-content itemscope itemtype=http://schema.org/Article lang=zh-CN><link href=https://nicksxs.me/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/ 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="AQS篇二 之 Condition 浅析笔记 | Nicksxs's Blog" itemprop=name><meta itemprop=description></span><header class=post-header><h1 itemprop="name headline" class=post-title>AQS篇二 之 Condition 浅析笔记</h1><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="创建时间:2021-02-21 21:27:06" datetime=2021-02-21T21:27:06+08:00>2021-02-21</time> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-calendar-check"></i> </span><span class=post-meta-item-text>更新于</span> <time title="修改时间:2022-06-11 22:45:11" datetime=2022-06-11T22:45:11+08:00 itemprop=dateModified>2022-06-11</time> </span><span class=post-meta-item><span class=post-meta-item-icon><i class="far fa-folder"></i> </span><span class=post-meta-item-text>分类于</span> <span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/ itemprop=url rel=index><span itemprop=name>Java</span></a> </span><span itemprop=about itemscope itemtype=http://schema.org/Thing><a href=/categories/Java/%E5%B9%B6%E5%8F%91/ itemprop=url rel=index><span itemprop=name>并发</span></a> </span></span><span class="post-meta-item leancloud_visitors" data-flag-title="AQS篇二 之 Condition 浅析笔记" id=/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/ 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 id=busuanzi_container_page_pv title=阅读次数><span class=post-meta-item-icon><i class="far fa-eye"></i> </span><span class=post-meta-item-text>阅读次数:</span> <span id=busuanzi_value_page_pv></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=/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/#disqus_thread itemprop=discussionUrl title=disqus><span class="post-comments-count disqus-comment-count" data-disqus-identifier=2021/02/21/AQS-之-Condition-浅析笔记/ itemprop=commentCount></span></a></span></div></div></header><div class=post-body itemprop=articleBody><p>Condition也是 AQS 中很重要的一块内容,可以先看段示例代码,这段代码应该来自于Doug Lea大大,可以在 javadoc 中的 <a href=https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html rel=noopener target=_blank>condition</a> 部分找到,其实大大原来写过基于 <code>synchronized</code> 实现的,后面我也贴下代码<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>concurrent<span class="token punctuation">.</span>locks<span class="token punctuation">.</span></span><span class="token class-name">Condition</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>concurrent<span class="token punctuation">.</span>locks<span class="token punctuation">.</span></span><span class="token class-name">Lock</span></span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token import"><span class="token namespace">java<span class="token punctuation">.</span>util<span class="token punctuation">.</span>concurrent<span class="token punctuation">.</span>locks<span class="token punctuation">.</span></span><span class="token class-name">ReentrantLock</span></span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">BoundedBuffer</span> <span class="token punctuation">{</span>
<span class="token keyword">final</span> <span class="token class-name">Lock</span> lock <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ReentrantLock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// condition 依赖于 lock 来产生</span>
<span class="token keyword">final</span> <span class="token class-name">Condition</span> notFull <span class="token operator">=</span> lock<span class="token punctuation">.</span><span class="token function">newCondition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">final</span> <span class="token class-name">Condition</span> notEmpty <span class="token operator">=</span> lock<span class="token punctuation">.</span><span class="token function">newCondition</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 对象池子,put 跟 take 的就是这里的</span>
<span class="token keyword">final</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> items <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token number">100</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> putptr<span class="token punctuation">,</span> takeptr<span class="token punctuation">,</span> count<span class="token punctuation">;</span>
<span class="token comment">// 生产</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token class-name">Object</span> x<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span>
<span class="token comment">// 这里也说明了,需要先拥有锁</span>
lock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>count <span class="token operator">==</span> items<span class="token punctuation">.</span>length<span class="token punctuation">)</span>
notFull<span class="token punctuation">.</span><span class="token function">await</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 队列已满,等待,直到 not full 才能继续生产</span>
items<span class="token punctuation">[</span>putptr<span class="token punctuation">]</span> <span class="token operator">=</span> x<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">++</span>putptr <span class="token operator">==</span> items<span class="token punctuation">.</span>length<span class="token punctuation">)</span> putptr <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token operator">++</span>count<span class="token punctuation">;</span>
notEmpty<span class="token punctuation">.</span><span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 生产成功,队列已经 not empty 了,发个通知出去</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
lock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">// 消费</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">take</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span>
lock<span class="token punctuation">.</span><span class="token function">lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>count <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span>
notEmpty<span class="token punctuation">.</span><span class="token function">await</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 队列为空,等待,直到队列 not empty,才能继续消费</span>
<span class="token class-name">Object</span> x <span class="token operator">=</span> items<span class="token punctuation">[</span>takeptr<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">++</span>takeptr <span class="token operator">==</span> items<span class="token punctuation">.</span>length<span class="token punctuation">)</span> takeptr <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token operator">--</span>count<span class="token punctuation">;</span>
notFull<span class="token punctuation">.</span><span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 被我消费掉一个,队列 not full 了,发个通知出去</span>
<span class="token keyword">return</span> x<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
lock<span class="token punctuation">.</span><span class="token function">unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>介绍下 Condition 的结构<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">ConditionObject</span> <span class="token keyword">implements</span> <span class="token class-name">Condition</span><span class="token punctuation">,</span> <span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>io<span class="token punctuation">.</span></span>Serializable</span> <span class="token punctuation">{</span>
<span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">long</span> serialVersionUID <span class="token operator">=</span> <span class="token number">1173984872572414699L</span><span class="token punctuation">;</span>
<span class="token comment">/** First node of condition queue. */</span>
<span class="token keyword">private</span> <span class="token keyword">transient</span> <span class="token class-name">Node</span> firstWaiter<span class="token punctuation">;</span>
<span class="token comment">/** Last node of condition queue. */</span>
<span class="token keyword">private</span> <span class="token keyword">transient</span> <span class="token class-name">Node</span> lastWaiter<span class="token punctuation">;</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>主要的就这么点,而且也复用了 AQS 阻塞队列或者大大叫 <code>lock queue</code>中同样的 Node 节点,只不过它没有使用其中的双向队列,也就是prev 和 next,而是在 Node 中的 nextWaiter,所以只是个单向的队列,没使用 next 其实还有个用处,后面会提到,看下结构的示意图<br><img data-src=https://img.nicksxs.com/uPic/Ss9oFX.png><br>然后主要是看两个方法,<code>await</code><code>signal</code>,<br>先来看下 await<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/**
* Implements interruptible condition wait.
* &LTol>
* &LTli> If current thread is interrupted, throw InterruptedException.
* &LTli> Save lock state returned by {@link #getState}.
* &LTli> Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* &LTli> Block until signalled or interrupted.
* &LTli> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* &LTli> If interrupted while blocked in step 4, throw InterruptedException.
* &LT/ol>
*/</span>
<span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">await</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 将当前节点包装成一个 condition waiter node 节点</span>
<span class="token class-name">Node</span> node <span class="token operator">=</span> <span class="token function">addConditionWaiter</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 完全释放占有的锁,这里需要是占有锁的线程</span>
<span class="token keyword">int</span> savedState <span class="token operator">=</span> <span class="token function">fullyRelease</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> interruptMode <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token comment">// 判断下是否在阻塞队列中,因为有可能被其他节点从等待队列移动到阻塞队列</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isOnSyncQueue</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// park等待,等待被唤醒</span>
<span class="token class-name">LockSupport</span><span class="token punctuation">.</span><span class="token function">park</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>interruptMode <span class="token operator">=</span> <span class="token function">checkInterruptWhileWaiting</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 被唤醒后进入阻塞队列,等待获取锁,这里继续用了fullyRelease返回的 state</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">acquireQueued</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> savedState<span class="token punctuation">)</span> <span class="token operator">&&</span> interruptMode <span class="token operator">!=</span> <span class="token constant">THROW_IE</span><span class="token punctuation">)</span>
interruptMode <span class="token operator">=</span> <span class="token constant">REINTERRUPT</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>node<span class="token punctuation">.</span>nextWaiter <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token comment">// clean up if cancelled</span>
<span class="token function">unlinkCancelledWaiters</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>interruptMode <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token function">reportInterruptAfterWait</span><span class="token punctuation">(</span>interruptMode<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>添加条件队列节点<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/**
* Adds a new waiter to wait queue.
* @return its new wait node
*/</span>
<span class="token keyword">private</span> <span class="token class-name">Node</span> <span class="token function">addConditionWaiter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Node</span> t <span class="token operator">=</span> lastWaiter<span class="token punctuation">;</span>
<span class="token comment">// If lastWaiter is cancelled, clean out.</span>
<span class="token comment">// 如果节点已经不是 CONDITION 状态了,表示已经取消了</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>t <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&&</span> t<span class="token punctuation">.</span>waitStatus <span class="token operator">!=</span> <span class="token class-name">Node</span><span class="token punctuation">.</span><span class="token constant">CONDITION</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 把等待队列中取消的节点清理出去</span>
<span class="token function">unlinkCancelledWaiters</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
t <span class="token operator">=</span> lastWaiter<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 把当前线程包装成waitStatus=CONDITION 的节点</span>
<span class="token class-name">Node</span> node <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Node</span><span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">currentThread</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Node</span><span class="token punctuation">.</span><span class="token constant">CONDITION</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 没有 lastWaiter 节点,直接是 firstWaiter</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>t <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
firstWaiter <span class="token operator">=</span> node<span class="token punctuation">;</span>
<span class="token keyword">else</span>
<span class="token comment">// 不然就接在 lastWaiter 后面</span>
t<span class="token punctuation">.</span>nextWaiter <span class="token operator">=</span> node<span class="token punctuation">;</span>
<span class="token comment">// 当前节点就会变成新的 lastWaiter</span>
lastWaiter <span class="token operator">=</span> node<span class="token punctuation">;</span>
<span class="token keyword">return</span> node<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>清理取消的节点<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/**
* Unlinks cancelled waiter nodes from condition queue.
* Called only while holding lock. This is called when
* cancellation occurred during condition wait, and upon
* insertion of a new waiter when lastWaiter is seen to have
* been cancelled. This method is needed to avoid garbage
* retention in the absence of signals. So even though it may
* require a full traversal, it comes into play only when
* timeouts or cancellations occur in the absence of
* signals. It traverses all nodes rather than stopping at a
* particular target to unlink all pointers to garbage nodes
* without requiring many re-traversals during cancellation
* storms.
*/</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">unlinkCancelledWaiters</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Node</span> t <span class="token operator">=</span> firstWaiter<span class="token punctuation">;</span>
<span class="token class-name">Node</span> trail <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token comment">// 循环遍历单向链表的节点,如果状态不是 CONDITION 就清出去</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>t <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Node</span> next <span class="token operator">=</span> t<span class="token punctuation">.</span>nextWaiter<span class="token punctuation">;</span>
<span class="token comment">// 循环链表操作,清掉取消的节点</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>t<span class="token punctuation">.</span>waitStatus <span class="token operator">!=</span> <span class="token class-name">Node</span><span class="token punctuation">.</span><span class="token constant">CONDITION</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
t<span class="token punctuation">.</span>nextWaiter <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>trail <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
firstWaiter <span class="token operator">=</span> next<span class="token punctuation">;</span>
<span class="token keyword">else</span>
trail<span class="token punctuation">.</span>nextWaiter <span class="token operator">=</span> next<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>next <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
lastWaiter <span class="token operator">=</span> trail<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">else</span>
trail <span class="token operator">=</span> t<span class="token punctuation">;</span>
t <span class="token operator">=</span> next<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>完全释放锁<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/**
* Invokes release with current state value; returns saved state.
* Cancels node and throws exception on failure.
* @param node the condition node for this wait
* @return previous sync state
*/</span>
<span class="token keyword">final</span> <span class="token keyword">int</span> <span class="token function">fullyRelease</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">boolean</span> failed <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 获取下当前的 state 值,因为是可重入的,所以这个值要保存下来</span>
<span class="token keyword">int</span> savedState <span class="token operator">=</span> <span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 这里还包含比较多操作,不过跟前面分析 AQS 的释放比较类似,不深入了</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">release</span><span class="token punctuation">(</span>savedState<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
failed <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token comment">// 返回这个值</span>
<span class="token keyword">return</span> savedState<span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalMonitorStateException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">finally</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>failed<span class="token punctuation">)</span>
node<span class="token punctuation">.</span>waitStatus <span class="token operator">=</span> <span class="token class-name">Node</span><span class="token punctuation">.</span><span class="token constant">CANCELLED</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>判断是否在阻塞队列中<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/**
* Returns true if a node, always one that was initially placed on
* a condition queue, is now waiting to reacquire on sync queue.
* @param node the node
* @return true if is reacquiring
*/</span>
<span class="token keyword">final</span> <span class="token keyword">boolean</span> <span class="token function">isOnSyncQueue</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 如果waitStatus 是 CONDITION 或者没有 prev 前置节点肯定就不在</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>node<span class="token punctuation">.</span>waitStatus <span class="token operator">==</span> <span class="token class-name">Node</span><span class="token punctuation">.</span><span class="token constant">CONDITION</span> <span class="token operator">||</span> node<span class="token punctuation">.</span>prev <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token comment">// 这里就是我前面提到的 next 的作用</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>node<span class="token punctuation">.</span>next <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token comment">// If has successor, it must be on queue</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token comment">// 从 tail 开始找,是否在阻塞队列中</span>
<span class="token comment">/*
* node.prev can be non-null, but not yet on queue because
* the CAS to place it on queue can fail. So we have to
* traverse from tail to make sure it actually made it. It
* will always be near the tail in calls to this method, and
* unless the CAS failed (which is unlikely), it will be
* there, so we hardly ever traverse much.
*/</span>
<span class="token keyword">return</span> <span class="token function">findNodeFromTail</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* Returns true if node is on sync queue by searching backwards from tail.
* Called only when needed by isOnSyncQueue.
* @return true if present
*/</span>
<span class="token keyword">private</span> <span class="token keyword">boolean</span> <span class="token function">findNodeFromTail</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token class-name">Node</span> t <span class="token operator">=</span> tail<span class="token punctuation">;</span>
<span class="token comment">// 从 tail 开始,从后往前找</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>t <span class="token operator">==</span> node<span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>t <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
t <span class="token operator">=</span> t<span class="token punctuation">.</span>prev<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>await 的逻辑差不多就是这样子,主要的就是把自己包成一个 Node 节点,waitStatus 的状态是 CONDITION,挂在等待队列的最后,然后完全释放锁,park 等待<h2 id=signal><a class=headerlink href=#signal title=signal></a>signal</h2><pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/**
* Moves the longest-waiting thread, if one exists, from the
* wait queue for this condition to the wait queue for the
* owning lock.
*
* @throws IllegalMonitorStateException if {@link #isHeldExclusively}
* returns {@code false}
*/</span>
<span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isHeldExclusively</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalMonitorStateException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// firstWaiter 肯定是最早开始等待的</span>
<span class="token class-name">Node</span> first <span class="token operator">=</span> firstWaiter<span class="token punctuation">;</span>
<span class="token comment">// 如果不为空就唤醒</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>first <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
<span class="token function">doSignal</span><span class="token punctuation">(</span>first<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* Removes and transfers nodes until hit non-cancelled one or
* null. Split out from signal in part to encourage compilers
* to inline the case of no waiters.
* @param first (non-null) the first node on condition queue
*/</span>
<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">doSignal</span><span class="token punctuation">(</span><span class="token class-name">Node</span> first<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">do</span> <span class="token punctuation">{</span>
<span class="token comment">// 因为要去唤醒 first 节点了,firstWaiter 需要再从后面找一个</span>
<span class="token comment">// 并且判断是否为空,如果是空的话就直接可以把 lastWaiter 设置成空了</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span>firstWaiter <span class="token operator">=</span> first<span class="token punctuation">.</span>nextWaiter<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
lastWaiter <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token comment">// first 不需要继续保存后面的 waiter 了,因为 firstWaiter 已经是 first 的后置节点了</span>
first<span class="token punctuation">.</span>nextWaiter <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token comment">// 如果 first 节点转移不成功,并且 firstWaiter 节点不为空,则继续进入循环</span>
<span class="token punctuation">}</span> <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">transferForSignal</span><span class="token punctuation">(</span>first<span class="token punctuation">)</span> <span class="token operator">&&</span>
<span class="token punctuation">(</span>first <span class="token operator">=</span> firstWaiter<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* Transfers a node from a condition queue onto sync queue.
* Returns true if successful.
* @param node the node
* @return true if successfully transferred (else the node was
* cancelled before signal)
*/</span>
<span class="token keyword">final</span> <span class="token keyword">boolean</span> <span class="token function">transferForSignal</span><span class="token punctuation">(</span><span class="token class-name">Node</span> node<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">/*
* If cannot change waitStatus, the node has been cancelled.
*/</span>
<span class="token comment">// 如果状态已经不是 CONDITION 就不会设置成功,返回 false</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">compareAndSetWaitStatus</span><span class="token punctuation">(</span>node<span class="token punctuation">,</span> <span class="token class-name">Node</span><span class="token punctuation">.</span><span class="token constant">CONDITION</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token comment">/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/</span>
<span class="token comment">// 调用跟aqs 第一篇中一样的 enq 方法进入阻塞队列,返回入队后的前一节点</span>
<span class="token class-name">Node</span> p <span class="token operator">=</span> <span class="token function">enq</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> ws <span class="token operator">=</span> p<span class="token punctuation">.</span>waitStatus<span class="token punctuation">;</span>
<span class="token comment">// 将前置节点状态设置成SIGNAL,表示后面有节点在等了</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>ws <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token function">compareAndSetWaitStatus</span><span class="token punctuation">(</span>p<span class="token punctuation">,</span> ws<span class="token punctuation">,</span> <span class="token class-name">Node</span><span class="token punctuation">.</span><span class="token constant">SIGNAL</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token class-name">LockSupport</span><span class="token punctuation">.</span><span class="token function">unpark</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>thread<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 返回 true,上一个方法的循环就退出了</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>这里其实就是把 condition 等待队列的第一个未取消的节点入队到阻塞队列去争锁<h2 id=附录><a class=headerlink href=#附录 title=附录></a>附录</h2><p><code>synchronized</code> 版的 BoundedBuffer<pre class="line-numbers language-java" data-language=java><code class=language-java><span class="token comment">/*
File: BoundedBuffer.java
Originally written by Doug Lea and released into the public domain.
This may be used for any purposes whatsoever without acknowledgment.
Thanks for the assistance and support of Sun Microsystems Labs,
and everyone contributing, testing, and using this code.
History:
Date Who What
11Jun1998 dl Create public version
17Jul1998 dl Simplified by eliminating wait counts
25aug1998 dl added peek
5May1999 dl replace % with conditional (slightly faster)
*/</span>
<span class="token keyword">package</span> <span class="token constant">EDU</span><span class="token punctuation">.</span>oswego<span class="token punctuation">.</span>cs<span class="token punctuation">.</span>dl<span class="token punctuation">.</span>util<span class="token punctuation">.</span>concurrent<span class="token punctuation">;</span>
<span class="token comment">/**
* Efficient array-based bounded buffer class.
* Adapted from CPJ, chapter 8, which describes design.
* &LTp>[&LTa href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. &LT/a>] &LTp>
**/</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">BoundedBuffer</span> <span class="token keyword">implements</span> <span class="token class-name">BoundedChannel</span> <span class="token punctuation">{</span>
<span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> array_<span class="token punctuation">;</span> <span class="token comment">// the elements</span>
<span class="token keyword">protected</span> <span class="token keyword">int</span> takePtr_ <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// circular indices</span>
<span class="token keyword">protected</span> <span class="token keyword">int</span> putPtr_ <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">protected</span> <span class="token keyword">int</span> usedSlots_ <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// length</span>
<span class="token keyword">protected</span> <span class="token keyword">int</span> emptySlots_<span class="token punctuation">;</span> <span class="token comment">// capacity - length</span>
<span class="token comment">/**
* Helper monitor to handle puts.
**/</span>
<span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token class-name">Object</span> putMonitor_ <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/**
* Create a BoundedBuffer with the given capacity.
* @exception IllegalArgumentException if capacity less or equal to zero
**/</span>
<span class="token keyword">public</span> <span class="token class-name">BoundedBuffer</span><span class="token punctuation">(</span><span class="token keyword">int</span> capacity<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IllegalArgumentException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>capacity <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
array_ <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">[</span>capacity<span class="token punctuation">]</span><span class="token punctuation">;</span>
emptySlots_ <span class="token operator">=</span> capacity<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* Create a buffer with the current default capacity
**/</span>
<span class="token keyword">public</span> <span class="token class-name">BoundedBuffer</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">(</span><span class="token class-name">DefaultChannelCapacity</span><span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* Return the number of elements in the buffer.
* This is only a snapshot value, that may change
* immediately after returning.
**/</span>
<span class="token keyword">public</span> <span class="token keyword">synchronized</span> <span class="token keyword">int</span> <span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> usedSlots_<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">int</span> <span class="token function">capacity</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> array_<span class="token punctuation">.</span>length<span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">incEmptySlots</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">synchronized</span><span class="token punctuation">(</span>putMonitor_<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token operator">++</span>emptySlots_<span class="token punctuation">;</span>
putMonitor_<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">protected</span> <span class="token keyword">synchronized</span> <span class="token keyword">void</span> <span class="token function">incUsedSlots</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token operator">++</span>usedSlots_<span class="token punctuation">;</span>
<span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token keyword">void</span> <span class="token function">insert</span><span class="token punctuation">(</span><span class="token class-name">Object</span> x<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// mechanics of put</span>
<span class="token operator">--</span>emptySlots_<span class="token punctuation">;</span>
array_<span class="token punctuation">[</span>putPtr_<span class="token punctuation">]</span> <span class="token operator">=</span> x<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">++</span>putPtr_ <span class="token operator">>=</span> array_<span class="token punctuation">.</span>length<span class="token punctuation">)</span> putPtr_ <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">protected</span> <span class="token keyword">final</span> <span class="token class-name">Object</span> <span class="token function">extract</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// mechanics of take</span>
<span class="token operator">--</span>usedSlots_<span class="token punctuation">;</span>
<span class="token class-name">Object</span> old <span class="token operator">=</span> array_<span class="token punctuation">[</span>takePtr_<span class="token punctuation">]</span><span class="token punctuation">;</span>
array_<span class="token punctuation">[</span>takePtr_<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">++</span>takePtr_ <span class="token operator">>=</span> array_<span class="token punctuation">.</span>length<span class="token punctuation">)</span> takePtr_ <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> old<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">peek</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">synchronized</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>usedSlots_ <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token keyword">return</span> array_<span class="token punctuation">[</span>takePtr_<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">else</span>
<span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token class-name">Object</span> x<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>x <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">synchronized</span><span class="token punctuation">(</span>putMonitor_<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>emptySlots_ <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span> putMonitor_<span class="token punctuation">.</span><span class="token function">wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
putMonitor_<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token function">insert</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">incUsedSlots</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token keyword">boolean</span> <span class="token function">offer</span><span class="token punctuation">(</span><span class="token class-name">Object</span> x<span class="token punctuation">,</span> <span class="token keyword">long</span> msecs<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>x <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalArgumentException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">synchronized</span><span class="token punctuation">(</span>putMonitor_<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> start <span class="token operator">=</span> <span class="token punctuation">(</span>msecs <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">?</span> <span class="token number">0</span> <span class="token operator">:</span> <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">long</span> waitTime <span class="token operator">=</span> msecs<span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>emptySlots_ <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>waitTime <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span> putMonitor_<span class="token punctuation">.</span><span class="token function">wait</span><span class="token punctuation">(</span>waitTime<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
putMonitor_<span class="token punctuation">.</span><span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
waitTime <span class="token operator">=</span> msecs <span class="token operator">-</span> <span class="token punctuation">(</span><span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> start<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">insert</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">incUsedSlots</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">take</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Object</span> old <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">synchronized</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>usedSlots_ <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token function">wait</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
old <span class="token operator">=</span> <span class="token function">extract</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">incEmptySlots</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> old<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">poll</span><span class="token punctuation">(</span><span class="token keyword">long</span> msecs<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">InterruptedException</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Thread</span><span class="token punctuation">.</span><span class="token function">interrupted</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">InterruptedException</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">Object</span> old <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">synchronized</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">long</span> start <span class="token operator">=</span> <span class="token punctuation">(</span>msecs <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">?</span> <span class="token number">0</span> <span class="token operator">:</span> <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">long</span> waitTime <span class="token operator">=</span> msecs<span class="token punctuation">;</span>
<span class="token keyword">while</span> <span class="token punctuation">(</span>usedSlots_ <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>waitTime <span class="token operator"><=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token function">wait</span><span class="token punctuation">(</span>waitTime<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
<span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">InterruptedException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">notify</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
waitTime <span class="token operator">=</span> msecs <span class="token operator">-</span> <span class="token punctuation">(</span><span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> start<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
old <span class="token operator">=</span> <span class="token function">extract</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">incEmptySlots</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> old<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span aria-hidden=true class=line-numbers-rows><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></div><footer class=post-footer><div class=reward-container><div>Buy me a coffee</div><button>赞赏</button><div class=post-reward><div><img alt="Nicksxs 微信" src=https://i.loli.net/2020/01/12/NUlWanT31E8LQGx.png><span>微信</span></div><div><img alt="Nicksxs 支付宝" src=https://ooo.0o0.ooo/2016/08/17/57b421e773057.jpg><span>支付宝</span></div></div></div><div class=post-copyright><ul><li class=post-copyright-author><strong>本文作者: </strong>Nicksxs<li class=post-copyright-link><strong>本文链接:</strong> <a title="AQS篇二 之 Condition 浅析笔记" href=https://nicksxs.me/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/>https://nicksxs.me/2021/02/21/AQS-之-Condition-浅析笔记/</a><li class=post-copyright-license><strong>版权声明: </strong>本博客所有文章除特别声明外,均采用 <a href=https://creativecommons.org/licenses/by-nc-sa/4.0/ rel=noopener target=_blank><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处!</ul></div><div class=post-tags><a href=/tags/java/ rel=tag># java</a><a href=/tags/%E5%B9%B6%E5%8F%91/ rel=tag># 并发</a><a href=/tags/j-u-c/ rel=tag># j.u.c</a><a href=/tags/aqs/ rel=tag># aqs</a><a href=/tags/condition/ rel=tag># condition</a><a href=/tags/await/ rel=tag># await</a><a href=/tags/signal/ rel=tag># signal</a><a href=/tags/lock/ rel=tag># lock</a><a href=/tags/unlock/ rel=tag># unlock</a></div><div class="addthis_inline_share_toolbox social-like"><script async src=https://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-64229fdd6f17a091></script></div><div class=post-nav><div class=post-nav-item><a href=/2021/02/14/AQS%E7%AF%87%E4%B8%80/ rel=prev title=AQS篇一><i class="fa fa-chevron-left"></i> AQS篇一</a></div><div class=post-nav-item><a href=/2021/02/28/%E9%97%B2%E8%81%8A%E4%B8%8B%E4%B9%98%E5%85%AC%E4%BA%A4%E7%9A%84%E7%94%A8%E6%88%B7%E4%BD%93%E9%AA%8C/ rel=next title=闲聊下乘公交的用户体验>闲聊下乘公交的用户体验 <i class="fa fa-chevron-right"></i></a></div></div></footer></article></div><div class=comments id=disqus_thread><noscript>Please enable JavaScript to view the comments powered by Disqus.</noscript></div></div></main><footer class=footer><div class=footer-inner><div class=beian><a href=https://beian.miit.gov.cn/ rel=noopener target=_blank>浙ICP备16002580号-2 </a><img alt src=/uploads/beian.png><a href=http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=33010602011094 rel=noopener target=_blank>浙公网安备 33010602011094号</a></div><div class=copyright>© <span itemprop=copyrightYear>2023</span><span class=with-love><i class="fa fa-heart"></i> </span><span class=author itemprop=copyrightHolder>Nicksxs</span></div><div class=busuanzi-count><span class=post-meta-item id=busuanzi_container_site_uv><span class=post-meta-item-icon><i class="fa fa-user"></i> </span><span class=site-uv title=总访客量><span id=busuanzi_value_site_uv></span> </span></span><span class=post-meta-item id=busuanzi_container_site_pv><span class=post-meta-item-icon><i class="fa fa-eye"></i> </span><span class=site-pv title=总访问量><span id=busuanzi_value_site_pv></span></span></span></div></div></footer><div aria-label=返回顶部 class=back-to-top role=button><i class="fa fa-arrow-up fa-lg"></i><span>0%</span></div><a aria-label="Follow me on GitHub" title="Follow me on GitHub" class=github-corner href=https://github.com/nicksxs rel=noopener target=_blank><svg viewbox="0 0 250 250" aria-hidden=true height=80 width=80><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" style="transform-origin:130px 106px" class=octo-arm fill=currentColor></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" class=octo-body fill=currentColor></path></svg></a><noscript><div class=noscript-warning>Theme NexT works best with JavaScript enabled</div></noscript><script crossorigin=anonymous integrity=sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY= src=https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js></script><script crossorigin=anonymous integrity=sha256-pvPw+upLPUjgMXY0G+8O0xUf+/Im1MZjXxxgOcBQBXU= src=https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js></script><script crossorigin=anonymous integrity=sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8= src=https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js></script><script crossorigin=anonymous integrity=sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc= src=https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js></script><script src=/js/comments.js></script><script src=/js/utils.js></script><script src=/js/motion.js></script><script src=/js/next-boot.js></script><script crossorigin=anonymous integrity=sha256-dyJcbGuYfdzNfifkHxYVd/rzeR6SLLcDFYEidcybldM= src=https://cdnjs.cloudflare.com/ajax/libs/algoliasearch/4.14.3/algoliasearch-lite.umd.js></script><script crossorigin=anonymous integrity=sha256-Nu8yqoXoRZEVYyZf4/eY1V4FsenbiCw85RY3gWjN3zQ= src=https://cdnjs.cloudflare.com/ajax/libs/instantsearch.js/4.49.2/instantsearch.production.min.js></script><script src=/js/third-party/search/algolia-search.js></script><script src=/js/third-party/fancybox.js></script><script async src=https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js></script><script class=next-config data-name=leancloud_visitors type=application/json>{"enable":true,"app_id":"ysza182Vghlqjdt7QiwGLLJy-gzGzoHsz","app_key":"s9GDqbn7gnGGkusf66YRVccw","server_url":"https://leancloud.cn","security":true}</script><script src=/js/third-party/statistics/lean-analytics.js></script><script crossorigin=anonymous integrity=sha256-yvJQOINiH9fWemHn0vCA5lsHWJaHs6/ZmO+1Ft04SvM= src=https://cdnjs.cloudflare.com/ajax/libs/quicklink/2.3.0/quicklink.umd.js></script><script class=next-config data-name=quicklink type=application/json>{"enable":true,"home":false,"archive":false,"delay":true,"timeout":3000,"priority":true,"url":"https://nicksxs.me/2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/"}</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>