{"id":877,"date":"2020-09-21T20:51:56","date_gmt":"2020-09-21T12:51:56","guid":{"rendered":"http:\/\/prayerlaputa.com\/?p=877"},"modified":"2020-09-21T20:51:56","modified_gmt":"2020-09-21T12:51:56","slug":"%e6%ba%90%e7%a0%81%e5%88%86%e6%9e%90%e4%b9%8bjava%e7%ba%bf%e7%a8%8b%e6%b1%a0threadpoolexecutor","status":"publish","type":"post","link":"http:\/\/prayerlaputa.com\/?p=877","title":{"rendered":"\u6e90\u7801\u5206\u6790\u4e4bJava\u7ebf\u7a0b\u6c60ThreadPoolExecutor"},"content":{"rendered":"<p>\u6211\u4e2a\u4eba\u89c9\u5f97\uff0c\u5b66\u4e60\u6e90\u7801\u7684\u59ff\u52bf\uff0c\u9996\u5148\u662f\u9700\u8981\u77e5\u9053\u60f3\u5b66\u4e60\u7684\u6846\u67b6\/\u5de5\u5177\u5982\u4f55\u4f7f\u7528\uff0c\u7136\u540e\u63a5\u4e0b\u6765\u518d\u53bb\u770b\u6e90\u7801\u6ce8\u91ca\uff0c\u770b\u770b\u5f53\u65f6\u4ee3\u7801\u4f5c\u8005\u662f\u5982\u4f55\u9610\u8ff0\u4ee3\u7801\u7684\uff0c\u518d\u53bb\u770b\u4ee3\u7801\u600e\u4e48\u7f16\u5199\uff0c\u6548\u679c\u624d\u6700\u4f73\u3002<\/p>\n<p>\u540c\u6837\u7684\uff0c\u63a5\u4e0b\u6765\u8981\u5206\u6790\u7684\u7ebf\u7a0b\u6c60\uff0c\u9996\u5148\u7528\u9014\u81ea\u4e0d\u5fc5\u8bf4\uff0c\u4e0d\u7ba1\u6709\u6ca1\u6709\u7528\u8fc7\uff0cThreadPoolExecutor\u7684\u8fd0\u884c\u673a\u5236\u3001\u4f20\u8bf4\u4e2d\u76847\u4e2a\u53c2\u6570(\u6838\u5fc3\u7ebf\u7a0b\u6570corePoolSize\u3001\u6700\u5927\u7ebf\u7a0b\u6570maxPoolSize\u3001\u7b49\u5f85\u65f6\u95f4keepAliveTime\u3001\u65f6\u95f4\u5355\u4f4dtimeUnit\u3001\u963b\u585e\u961f\u5217blockingQueue\u3001\u7ebf\u7a0b\u5de5\u5382threadFactory\u3001\u62d2\u7edd\u7b56\u7565rejectHandler)\uff0c\u76f8\u4fe1\u5927\u5bb6\u90fd\u5df2\u7ecf\u719f\u7ec3\u638c\u63e1\uff0c\u6b64\u5904\u4e0d\u518d\u8d58\u8ff0\u3002<\/p>\n<p>\u63a5\u4e0b\u6765\u7b80\u5355\u8fc7\u4e00\u4e0bThreadPoolExecutor\u7684\u6ce8\u91ca\u3002<br \/>\n<!--more--><\/p>\n<h2>0. \u6e90\u7801\u6ce8\u91ca\u4e2d\u7684\u5173\u952e\u70b9<\/h2>\n<p>ThreadPoolExecutor\u7684\u7c7b\u6ce8\u91ca\u4e2d\uff0c\u4e3b\u8981\u9610\u8ff0\u5982\u4e0b\u5185\u5bb9\uff1a<\/p>\n<ul>\n<li>\u6709\u5173\u8fd0\u884c\u673a\u5236\u30017\u4e2a\u53c2\u6570\u5982\u4f55\u4f7f\u7528\u4e0e\u914d\u5408\n<ul>\n<li>\u8fd8\u6709\u4e00\u4e9b\u7ec6\u8282\uff0c\u6bd4\u5982\u963b\u585e\u961f\u5217\uff0c\u53ef\u4ee5\u67093\u79cd\u9009\u62e9\uff1a<\/li>\n<li>direct handoff<\/li>\n<li>unbounded queue<\/li>\n<li>bounded queue<\/li>\n<li>\u5176\u4ed6\u53ef\u80fd\u6709\u7528\u7684\u4fe1\u606f\uff1a<\/li>\n<li>\u7ebf\u7a0b\u6c60\u7684hook\u65b9\u6cd5\uff1abeforeExecute(Thread, Runnable)\uff0c afterExecute(Runnable, Throwable)\u3002\u82e5hook\u629b\u51fa\u5f02\u5e38\uff0c\u5219\u5f53\u524d\u7ebf\u7a0b\u4e5f\u4f1a\u5f02\u5e38\u7ec8\u6b62\u3002<\/li>\n<li>getQueue() \u53ef\u4ee5\u83b7\u53d6\u5de5\u4f5c\u961f\u5217\uff0c\u53ef\u4ee5\u7528\u6765monitor\u548cdebug\uff0c\u4e0d\u63a8\u8350\u7528\u4e8e\u5176\u4ed6\u7528\u9014\u3002\u63d0\u4f9b\u4e86\u4e24\u4e2a\u63a5\u53e3\uff1a remove(Runnable) \uff0c purge()<\/li>\n<li>\u7ebf\u7a0b\u6c60\u5bf9\u8c61\u5728\u7a0b\u5e8f\u4e2d\u4e0d\u88ab\u5f15\u7528\uff0c\u5e76\u4e14\u6ca1\u6709\u7ebf\u7a0b\u65f6\uff0c\u8be5\u7ebf\u7a0b\u6c60\u5c06\u4f1a\u88ab\u81ea\u52a8\u5173\u95ed\u3002<\/li>\n<\/ul>\n<\/li>\n<li>\u7ebf\u7a0b\u6c60\u72b6\u6001\u7684\u8bf4\u660e\n<ul>\n<li>ThreadPoolExecutor\u6709\u4e00\u4e2aAtomicInteger\u53d8\u91cfctl\u8868\u793a\uff0c\u8be5\u53d8\u91cf\u5305\u542b\u4e86\u4e24\u4e2a\u542b\u4e49\uff1a<\/p>\n<\/li>\n<li>\n<p>\u9ad83\u4f4d\u8868\u793a\u5f53\u524d\u7ebf\u7a0b\u6c60\u72b6\u6001<\/p>\n<ul>\n<li>\n&#8220;`<br \/>\n&lt;\/li&gt;<br \/>\n&lt;li&gt;RUNNING:  Accept new tasks and process queued tasks&lt;\/li&gt;<br \/>\n&lt;li&gt;SHUTDOWN: Don&#039;t accept new tasks, but process queued tasks&lt;\/li&gt;<br \/>\n&lt;li&gt;STOP:     Don&#039;t accept new tasks, don&#039;t process queued tasks,&lt;\/li&gt;<br \/>\n&lt;li&gt;and interrupt in-progress tasks&lt;\/li&gt;<br \/>\n&lt;li&gt;TIDYING:  All tasks have terminated, workerCount is zero,&lt;\/li&gt;<br \/>\n&lt;li&gt;the thread transitioning to state TIDYING&lt;\/li&gt;<br \/>\n&lt;li&gt;will run the terminated() hook method&lt;\/li&gt;<br \/>\n&lt;li&gt;TERMINATED: terminated() has completed&lt;\/li&gt;<br \/>\n&lt;\/ul&gt;<\/p>\n<p>&lt;pre&gt;&lt;code class=&quot;line-numbers&quot;&gt;- \u72b6\u6001\u8f6c\u79fb\u3002\u8fd9\u4e9b\u72b6\u6001\u652f\u6301\u6bd4\u8f83\uff0c\u56e0\u4e3aJDK\u5b9e\u73b0\u65f6\uff0cThe runState monotonically increases over time, but need not hit each state. <\/p>\n<p>&lt;\/code&gt;&lt;\/pre&gt;<\/p>\n<p>&lt;ul&gt;<br \/>\n&lt;li&gt;RUNNING -&gt; SHUTDOWN&lt;\/li&gt;<br \/>\n&lt;li&gt;On invocation of shutdown(), perhaps implicitly in finalize()&lt;\/li&gt;<br \/>\n&lt;li&gt;(RUNNING or SHUTDOWN) -&gt; STOP&lt;\/li&gt;<br \/>\n&lt;li&gt;On invocation of shutdownNow()&lt;\/li&gt;<br \/>\n&lt;li&gt;SHUTDOWN -&gt; TIDYING&lt;\/li&gt;<br \/>\n&lt;li&gt;When both queue and pool are empty&lt;\/li&gt;<br \/>\n&lt;li&gt;STOP -&gt; TIDYING&lt;\/li&gt;<br \/>\n&lt;li&gt;When pool is empty&lt;\/li&gt;<br \/>\n&lt;li&gt;TIDYING -&gt; TERMINATED&lt;\/li&gt;<br \/>\n&lt;li&gt;When the terminated() hook method has completed<\/p>\n<p>&#8220;`\n<\/li>\n<\/ul>\n<\/li>\n<li>\u5269\u4f59\u7684\u4f4e29\u4f4d\u8868\u793a\u7ebf\u7a0b\u6c60\u7684\u6570\u91cf\uff08\u6240\u4ee5\u76ee\u524d\u7684\u7248\u672c\u53ea\u6709\u652f\u63012^29-1\u4e2a\u7ebf\u7a0b\uff09<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u4e0b\u9762\u5c06\u7ed3\u5408\u4ee3\u7801\uff0c\u89e3\u8bf4\u7ebf\u7a0b\u6c60\u7684\u5173\u952e\u6d41\u7a0b\u3002<\/p>\n<h2>1. \u5e38\u7528\u53d8\u91cf\u7684\u89e3\u91ca<\/h2>\n<pre><code class=\"language-java line-numbers\">\/\/ 1. `ctl`\uff0c\u53ef\u4ee5\u770b\u505a\u4e00\u4e2aint\u7c7b\u578b\u7684\u6570\u5b57\uff0c\u9ad83\u4f4d\u8868\u793a\u7ebf\u7a0b\u6c60\u72b6\u6001\uff0c\u4f4e29\u4f4d\u8868\u793aworker\u6570\u91cf\nprivate final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));\n\/\/ 2. `COUNT_BITS`\uff0c`Integer.SIZE`\u4e3a32\uff0c\u6240\u4ee5`COUNT_BITS`\u4e3a29\nprivate static final int COUNT_BITS = Integer.SIZE - 3;\n\/\/ 3. `CAPACITY`\uff0c\u7ebf\u7a0b\u6c60\u5141\u8bb8\u7684\u6700\u5927\u7ebf\u7a0b\u6570\u30021\u5de6\u79fb29\u4f4d\uff0c\u7136\u540e\u51cf1\uff0c\u5373\u4e3a 2^29 - 1\uff0c\u4e8c\u8fdb\u5236\u8868\u793a\u4e3a\u8fde\u7eed\u768429\u4e2a1\nprivate static final int CAPACITY   = (1 &lt;&lt; COUNT_BITS) - 1;\n\n\/\/ runState is stored in the high-order bits\n\/\/ 4. \u7ebf\u7a0b\u6c60\u67095\u79cd\u72b6\u6001\uff0c\u6309\u5927\u5c0f\u6392\u5e8f\u5982\u4e0b\uff1aRUNNING &lt; SHUTDOWN &lt; STOP &lt; TIDYING &lt; TERMINATED .  \u6b64\u5904RUNNING\u5b9e\u9645\u4e0a\u662f-(1&lt;&lt;COUNT_BITS)\uff0c\u662f\u8d1f\u6570\u3002\nprivate static final int RUNNING    = -1 &lt;&lt; COUNT_BITS;\nprivate static final int SHUTDOWN   =  0 &lt;&lt; COUNT_BITS;\nprivate static final int STOP       =  1 &lt;&lt; COUNT_BITS;\nprivate static final int TIDYING    =  2 &lt;&lt; COUNT_BITS;\nprivate static final int TERMINATED =  3 &lt;&lt; COUNT_BITS;\n\n\/\/ Packing and unpacking ctl\n\/\/ 5. `runStateOf()`\uff0c\u83b7\u53d6\u7ebf\u7a0b\u6c60\u72b6\u6001\uff0c\u901a\u8fc7\u6309\u4f4d\u4e0e\u64cd\u4f5c\uff0c\u4f4e29\u4f4d\u5c06\u5168\u90e8\u53d8\u62100\nprivate static int runStateOf(int c)     { return c &amp; ~CAPACITY; }\n\/\/ 6. `workerCountOf()`\uff0c\u83b7\u53d6\u7ebf\u7a0b\u6c60worker\u6570\u91cf\uff0c\u901a\u8fc7\u6309\u4f4d\u4e0e\u64cd\u4f5c\uff0c\u9ad83\u4f4d\u5c06\u5168\u90e8\u53d8\u62100\nprivate static int workerCountOf(int c)  { return c &amp; CAPACITY; }\n\/\/ 7. `ctlOf()`\uff0c\u6839\u636e\u7ebf\u7a0b\u6c60\u72b6\u6001\u548c\u7ebf\u7a0b\u6c60worker\u6570\u91cf\uff0c\u751f\u6210ctl\u503c\nprivate static int ctlOf(int rs, int wc) { return rs | wc; }\n\n\/*\n * Bit field accessors that don't require unpacking ctl.\n * These depend on the bit layout and on workerCount being never negative.\n *\/\n\/\/ 8. `runStateLessThan()`\uff0c\u7ebf\u7a0b\u6c60\u72b6\u6001\u5c0f\u4e8exx\nprivate static boolean runStateLessThan(int c, int s) {\n    return c &lt; s;\n}\n\/\/ 9. `runStateAtLeast()`\uff0c\u7ebf\u7a0b\u6c60\u72b6\u6001\u5927\u4e8e\u7b49\u4e8exx\nprivate static boolean runStateAtLeast(int c, int s) {\n    return c &gt;= s;\n}\n<\/code><\/pre>\n<h2>2. \u6784\u9020\u65b9\u6cd5<\/h2>\n<pre><code class=\"language-java line-numbers\">public ThreadPoolExecutor(int corePoolSize,\n                          int maximumPoolSize,\n                          long keepAliveTime,\n                          TimeUnit unit,\n                          BlockingQueue&lt;Runnable&gt; workQueue,\n                          ThreadFactory threadFactory,\n                          RejectedExecutionHandler handler) {\n    \/\/ \u57fa\u672c\u7c7b\u578b\u53c2\u6570\u6821\u9a8c\n    if (corePoolSize &lt; 0 ||\n        maximumPoolSize &lt;= 0 ||\n        maximumPoolSize &lt; corePoolSize ||\n        keepAliveTime &lt; 0)\n        throw new IllegalArgumentException();\n    \/\/ \u7a7a\u6307\u9488\u6821\u9a8c\n    if (workQueue == null || threadFactory == null || handler == null)\n        throw new NullPointerException();\n    this.corePoolSize = corePoolSize;\n    this.maximumPoolSize = maximumPoolSize;\n    this.workQueue = workQueue;\n    \/\/ \u6839\u636e\u4f20\u5165\u53c2\u6570`unit`\u548c`keepAliveTime`\uff0c\u5c06\u5b58\u6d3b\u65f6\u95f4\u8f6c\u6362\u4e3a\u7eb3\u79d2\u5b58\u5230\u53d8\u91cf`keepAliveTime `\u4e2d\n    this.keepAliveTime = unit.toNanos(keepAliveTime);\n    this.threadFactory = threadFactory;\n    this.handler = handler;\n}\n<\/code><\/pre>\n<h2>3. \u63d0\u4ea4\u6267\u884ctask\u7684\u8fc7\u7a0b<\/h2>\n<pre><code class=\"language-java line-numbers\">public void execute(Runnable command) {\n    if (command == null)\n        throw new NullPointerException();\n    \/*\n     * Proceed in 3 steps:\n     *\n     * 1. If fewer than corePoolSize threads are running, try to\n     * start a new thread with the given command as its first\n     * task.  The call to addWorker atomically checks runState and\n     * workerCount, and so prevents false alarms that would add\n     * threads when it shouldn't, by returning false.\n     *\n     * 2. If a task can be successfully queued, then we still need\n     * to double-check whether we should have added a thread\n     * (because existing ones died since last checking) or that\n     * the pool shut down since entry into this method. So we\n     * recheck state and if necessary roll back the enqueuing if\n     * stopped, or start a new thread if there are none.\n     *\n     * 3. If we cannot queue task, then we try to add a new\n     * thread.  If it fails, we know we are shut down or saturated\n     * and so reject the task.\n     *\/\n    int c = ctl.get();\n    \/\/ worker\u6570\u91cf\u6bd4\u6838\u5fc3\u7ebf\u7a0b\u6570\u5c0f\uff0c\u76f4\u63a5\u521b\u5efaworker\u6267\u884c\u4efb\u52a1\n    if (workerCountOf(c) &lt; corePoolSize) {\n        if (addWorker(command, true))\n            return;\n        c = ctl.get();\n    }\n    \/\/ worker\u6570\u91cf\u8d85\u8fc7\u6838\u5fc3\u7ebf\u7a0b\u6570\uff0c\u4efb\u52a1\u76f4\u63a5\u8fdb\u5165\u961f\u5217\n    if (isRunning(c) &amp;&amp; workQueue.offer(command)) {\n        int recheck = ctl.get();\n        \/\/ \u7ebf\u7a0b\u6c60\u72b6\u6001\u4e0d\u662fRUNNING\u72b6\u6001\uff0c\u8bf4\u660e\u6267\u884c\u8fc7shutdown\u547d\u4ee4\uff0c\u9700\u8981\u5bf9\u65b0\u52a0\u5165\u7684\u4efb\u52a1\u6267\u884creject()\u64cd\u4f5c\u3002\n        \/\/ \u8fd9\u513f\u4e3a\u4ec0\u4e48\u9700\u8981recheck\uff0c\u662f\u56e0\u4e3a\u4efb\u52a1\u5165\u961f\u5217\u524d\u540e\uff0c\u7ebf\u7a0b\u6c60\u7684\u72b6\u6001\u53ef\u80fd\u4f1a\u53d1\u751f\u53d8\u5316\u3002\n        if (! isRunning(recheck) &amp;&amp; remove(command))\n            reject(command);\n        \/\/ \u8fd9\u513f\u4e3a\u4ec0\u4e48\u9700\u8981\u5224\u65ad0\u503c\uff0c\u4e3b\u8981\u662f\u5728\u7ebf\u7a0b\u6c60\u6784\u9020\u65b9\u6cd5\u4e2d\uff0c\u6838\u5fc3\u7ebf\u7a0b\u6570\u5141\u8bb8\u4e3a0\n        else if (workerCountOf(recheck) == 0)\n            addWorker(null, false);\n    }\n    \/\/ \u5982\u679c\u7ebf\u7a0b\u6c60\u4e0d\u662f\u8fd0\u884c\u72b6\u6001\uff0c\u6216\u8005\u4efb\u52a1\u8fdb\u5165\u961f\u5217\u5931\u8d25\uff0c\u5219\u5c1d\u8bd5\u521b\u5efaworker\u6267\u884c\u4efb\u52a1\u3002\n    \/\/ \u8fd9\u513f\u67093\u70b9\u9700\u8981\u6ce8\u610f\uff1a\n    \/\/ 1. \u7ebf\u7a0b\u6c60\u4e0d\u662f\u8fd0\u884c\u72b6\u6001\u65f6\uff0caddWorker\u5185\u90e8\u4f1a\u5224\u65ad\u7ebf\u7a0b\u6c60\u72b6\u6001\n    \/\/ 2. addWorker\u7b2c2\u4e2a\u53c2\u6570\u8868\u793a\u662f\u5426\u521b\u5efa\u6838\u5fc3\u7ebf\u7a0b\n    \/\/ 3. addWorker\u8fd4\u56defalse\uff0c\u5219\u8bf4\u660e\u4efb\u52a1\u6267\u884c\u5931\u8d25\uff0c\u9700\u8981\u6267\u884creject\u64cd\u4f5c\n    else if (!addWorker(command, false))\n        reject(command);\n}\n<\/code><\/pre>\n<h2>4. addworker\u6e90\u7801\u89e3\u6790<\/h2>\n<pre><code class=\"language-java line-numbers\">private boolean addWorker(Runnable firstTask, boolean core) {\n    retry:\n    \/\/\u5916\u5c42\u81ea\u65cb\n    for (;;) {\n        int c = ctl.get();\n        int rs = runStateOf(c);\n\n        \/\/ \u8fd9\u4e2a\u6761\u4ef6\u5199\u5f97\u6bd4\u8f83\u96be\u61c2\uff0c\u548c\u4e0b\u9762\u7684\u6761\u4ef6\u7b49\u4ef7\n        \/\/ (rs &gt; SHUTDOWN) || \n        \/\/ (rs == SHUTDOWN &amp;&amp; firstTask != null) || \n        \/\/ (rs == SHUTDOWN &amp;&amp; workQueue.isEmpty())\n        \/\/ 1. \u7ebf\u7a0b\u6c60\u72b6\u6001\u5927\u4e8eSHUTDOWN\u65f6\uff0c\u76f4\u63a5\u8fd4\u56defalse\n        \/\/ 2. \u7ebf\u7a0b\u6c60\u72b6\u6001\u7b49\u4e8eSHUTDOWN\uff0c\u4e14firstTask\u4e0d\u4e3anull\uff0c\u76f4\u63a5\u8fd4\u56defalse\n        \/\/ 3. \u7ebf\u7a0b\u6c60\u72b6\u6001\u7b49\u4e8eSHUTDOWN\uff0c\u4e14\u961f\u5217\u4e3a\u7a7a\uff0c\u76f4\u63a5\u8fd4\u56defalse\n        \/\/ Check if queue empty only if necessary.\n        if (rs &gt;= SHUTDOWN &amp;&amp;\n            ! (rs == SHUTDOWN &amp;&amp;\n               firstTask == null &amp;&amp;\n               ! workQueue.isEmpty()))\n            return false;\n\n        \/\/ \u5185\u5c42\u81ea\u65cb\n        for (;;) {\n            int wc = workerCountOf(c);\n            \/\/ worker\u6570\u91cf\u8d85\u8fc7\u5bb9\u91cf\uff0c\u76f4\u63a5\u8fd4\u56defalse\n            if (wc &gt;= CAPACITY ||\n                wc &gt;= (core ? corePoolSize : maximumPoolSize))\n                return false;\n             \/\/ \u4f7f\u7528CAS\u7684\u65b9\u5f0f\u589e\u52a0worker\u6570\u91cf\u3002\n            \/\/ \u82e5\u589e\u52a0\u6210\u529f\uff0c\u5219\u76f4\u63a5\u8df3\u51fa\u5916\u5c42\u5faa\u73af\u8fdb\u5165\u5230\u7b2c\u4e8c\u90e8\u5206\n            if (compareAndIncrementWorkerCount(c))\n                break retry;\n            c = ctl.get();  \/\/ Re-read ctl\n            \/\/ \u7ebf\u7a0b\u6c60\u72b6\u6001\u53d1\u751f\u53d8\u5316\uff0c\u5bf9\u5916\u5c42\u5faa\u73af\u8fdb\u884c\u81ea\u65cb\n            if (runStateOf(c) != rs)\n                continue retry;\n             \/\/ \u5176\u4ed6\u60c5\u51b5\uff0c\u76f4\u63a5\u5185\u5c42\u5faa\u73af\u8fdb\u884c\u81ea\u65cb\u5373\u53ef\n            \/\/ else CAS failed due to workerCount change; retry inner loop\n        }\n    }\n\n    boolean workerStarted = false;\n    boolean workerAdded = false;\n    Worker w = null;\n    try {\n        w = new Worker(firstTask);\n        final Thread t = w.thread;\n        if (t != null) {\n            final ReentrantLock mainLock = this.mainLock;\n             \/\/ worker\u7684\u6dfb\u52a0\u5fc5\u987b\u662f\u4e32\u884c\u7684\uff0c\u56e0\u6b64\u9700\u8981\u52a0\u9501\n            mainLock.lock();\n            try {\n                \/\/ \u8fd9\u513f\u9700\u8981\u91cd\u65b0\u68c0\u67e5\u7ebf\u7a0b\u6c60\u72b6\u6001\n                \/\/ Recheck while holding lock.\n                \/\/ Back out on ThreadFactory failure or if\n                \/\/ shut down before lock acquired.\n                int rs = runStateOf(ctl.get());\n\n                if (rs &lt; SHUTDOWN ||\n                    (rs == SHUTDOWN &amp;&amp; firstTask == null)) {\n                    \/\/ worker\u5df2\u7ecf\u8c03\u7528\u8fc7\u4e86start()\u65b9\u6cd5\uff0c\u5219\u4e0d\u518d\u521b\u5efaworker\n                    if (t.isAlive()) \/\/ precheck that t is startable\n                        throw new IllegalThreadStateException();\n                    \/\/ worker\u521b\u5efa\u5e76\u6dfb\u52a0\u5230workers\u6210\u529f\n                    workers.add(w);\n                    \/\/ \u66f4\u65b0`largestPoolSize`\u53d8\u91cf\n                    int s = workers.size();\n                    if (s &gt; largestPoolSize)\n                        largestPoolSize = s;\n                    workerAdded = true;\n                }\n            } finally {\n                mainLock.unlock();\n            }\n            \/\/ \u542f\u52a8worker\u7ebf\u7a0b\n            if (workerAdded) {\n                t.start();\n                workerStarted = true;\n            }\n        }\n    } finally {\n        \/\/ worker\u7ebf\u7a0b\u542f\u52a8\u5931\u8d25\uff0c\u8bf4\u660e\u7ebf\u7a0b\u6c60\u72b6\u6001\u53d1\u751f\u4e86\u53d8\u5316\uff08\u5173\u95ed\u64cd\u4f5c\u88ab\u6267\u884c\uff09\uff0c\u9700\u8981\u8fdb\u884cshutdown\u76f8\u5173\u64cd\u4f5c\n        if (! workerStarted)\n            addWorkerFailed(w);\n    }\n    return workerStarted;\n}\n<\/code><\/pre>\n<h2>5. \u7ebf\u7a0b\u6c60worker\u4efb\u52a1\u5355\u5143<\/h2>\n<pre><code class=\"language-java line-numbers\">private final class Worker\n    extends AbstractQueuedSynchronizer\n    implements Runnable\n{\n    \/**\n     * This class will never be serialized, but we provide a\n     * serialVersionUID to suppress a javac warning.\n     *\/\n    private static final long serialVersionUID = 6138294804551838833L;\n\n    \/** Thread this worker is running in.  Null if factory fails. *\/\n    final Thread thread;\n    \/** Initial task to run.  Possibly null. *\/\n    Runnable firstTask;\n    \/** Per-thread task counter *\/\n    volatile long completedTasks;\n\n    \/**\n     * Creates with given first task and thread from ThreadFactory.\n     * @param firstTask the first task (null if none)\n     *\/\n    Worker(Runnable firstTask) {\n        setState(-1); \/\/ inhibit interrupts until runWorker\n        this.firstTask = firstTask;\n        \/\/ \u8fd9\u513f\u662fWorker\u7684\u5173\u952e\u6240\u5728\uff0c\u4f7f\u7528\u4e86\u7ebf\u7a0b\u5de5\u5382\u521b\u5efa\u4e86\u4e00\u4e2a\u7ebf\u7a0b\u3002\u4f20\u5165\u7684\u53c2\u6570\u4e3a\u5f53\u524dworker\n        this.thread = getThreadFactory().newThread(this);\n    }\n\n    \/** Delegates main run loop to outer runWorker  *\/\n    public void run() {\n        \/\/\u6b64\u5904\u5206\u6790\u53c2\u89c1 `\u6838\u5fc3\u7ebf\u7a0b\u6267\u884c\u903b\u8f91-runworker`\n        runWorker(this);\n    }\n\n    \/\/ \u7701\u7565\u4ee3\u7801...\n}\n<\/code><\/pre>\n<h2>6. \u6838\u5fc3\u7ebf\u7a0b\u6267\u884c\u903b\u8f91-runworker<\/h2>\n<pre><code class=\"language-java line-numbers\">final void runWorker(Worker w) {\n    Thread wt = Thread.currentThread();\n    Runnable task = w.firstTask;\n    w.firstTask = null;\n    \/\/ \u8c03\u7528unlock()\u662f\u4e3a\u4e86\u8ba9\u5916\u90e8\u53ef\u4ee5\u4e2d\u65ad\n    w.unlock(); \/\/ allow interrupts\n    \/\/ \u8fd9\u4e2a\u53d8\u91cf\u7528\u4e8e\u5224\u65ad\u662f\u5426\u8fdb\u5165\u8fc7\u81ea\u65cb\uff08while\u5faa\u73af\uff09\n    boolean completedAbruptly = true;\n    try {\n        \/\/ \u8fd9\u513f\u662f\u81ea\u65cb\n        \/\/ 1. \u5982\u679cfirstTask\u4e0d\u4e3anull\uff0c\u5219\u6267\u884cfirstTask\uff1b\n        \/\/ 2. \u5982\u679cfirstTask\u4e3anull\uff0c\u5219\u8c03\u7528getTask()\u4ece\u961f\u5217\u83b7\u53d6\u4efb\u52a1\u3002\n        \/\/ 3. \u963b\u585e\u961f\u5217\u7684\u7279\u6027\u5c31\u662f\uff1a\u5f53\u961f\u5217\u4e3a\u7a7a\u65f6\uff0c\u5f53\u524d\u7ebf\u7a0b\u4f1a\u88ab\u963b\u585e\u7b49\u5f85\n        while (task != null || (task = getTask()) != null) {\n            \/\/ \u8fd9\u513f\u5bf9worker\u8fdb\u884c\u52a0\u9501\uff0c\u662f\u4e3a\u4e86\u8fbe\u5230\u4e0b\u9762\u7684\u76ee\u7684\n            \/\/ 1. \u964d\u4f4e\u9501\u8303\u56f4\uff0c\u63d0\u5347\u6027\u80fd\n            \/\/ 2. \u4fdd\u8bc1\u6bcf\u4e2aworker\u6267\u884c\u7684\u4efb\u52a1\u662f\u4e32\u884c\u7684\n            w.lock();\n            \/\/ If pool is stopping, ensure thread is interrupted;\n            \/\/ if not, ensure thread is not interrupted.  This\n            \/\/ requires a recheck in second case to deal with\n            \/\/ shutdownNow race while clearing interrupt\n            \/\/ \u5982\u679c\u7ebf\u7a0b\u6c60\u6b63\u5728\u505c\u6b62\uff0c\u5219\u5bf9\u5f53\u524d\u7ebf\u7a0b\u8fdb\u884c\u4e2d\u65ad\u64cd\u4f5c\n            if ((runStateAtLeast(ctl.get(), STOP) ||\n                 (Thread.interrupted() &amp;&amp;\n                  runStateAtLeast(ctl.get(), STOP))) &amp;&amp;\n                !wt.isInterrupted())\n                wt.interrupt();\n            \/\/ \u6267\u884c\u4efb\u52a1\uff0c\u4e14\u5728\u6267\u884c\u524d\u540e\u901a\u8fc7`beforeExecute()`\u548c`afterExecute()`\u6765\u6269\u5c55\u5176\u529f\u80fd\u3002\n            \/\/ \u8fd9\u4e24\u4e2a\u65b9\u6cd5\u5728\u5f53\u524d\u7c7b\u91cc\u9762\u4e3a\u7a7a\u5b9e\u73b0\u3002\n            try {\n                beforeExecute(wt, task);\n                Throwable thrown = null;\n                try {\n                    task.run();\n                } catch (RuntimeException x) {\n                    thrown = x; throw x;\n                } catch (Error x) {\n                    thrown = x; throw x;\n                } catch (Throwable x) {\n                    thrown = x; throw new Error(x);\n                } finally {\n                    afterExecute(task, thrown);\n                }\n            } finally {\n                \/\/ \u5e2e\u52a9gc\n                task = null;\n                \/\/ \u5df2\u5b8c\u6210\u4efb\u52a1\u6570\u52a0\u4e00 \n                w.completedTasks++;\n                w.unlock();\n            }\n        }\n        completedAbruptly = false;\n    } finally {\n        \/\/ \u81ea\u65cb\u64cd\u4f5c\u88ab\u9000\u51fa\uff0c\u8bf4\u660e\u7ebf\u7a0b\u6c60\u6b63\u5728\u7ed3\u675f\n        processWorkerExit(w, completedAbruptly);\n    }\n}\n<\/code><\/pre>\n<h2>\u53c2\u8003\u8d44\u6599<\/h2>\n<ul>\n<li><a class=\"wp-editor-md-post-content-link\" href=\"https:\/\/github.com\/bjmashibing\/JUC\/\">ThreadPoolExecutor\u6e90\u7801\u89e3\u6790<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u6211\u4e2a\u4eba\u89c9\u5f97\uff0c\u5b66\u4e60\u6e90\u7801\u7684\u59ff\u52bf\uff0c\u9996\u5148\u662f\u9700\u8981\u77e5\u9053\u60f3\u5b66\u4e60\u7684\u6846\u67b6\/\u5de5\u5177\u5982\u4f55\u4f7f\u7528\uff0c\u7136\u540e\u63a5\u4e0b\u6765\u518d\u53bb\u770b\u6e90\u7801\u6ce8\u91ca\uff0c\u770b\u770b\u5f53\u65f6\u4ee3\u7801\u4f5c <a href='http:\/\/prayerlaputa.com\/?p=877' class='excerpt-more'>[&#8230;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[6,99,18],"tags":[33,101,81,50],"_links":{"self":[{"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=\/wp\/v2\/posts\/877"}],"collection":[{"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=877"}],"version-history":[{"count":1,"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=\/wp\/v2\/posts\/877\/revisions"}],"predecessor-version":[{"id":878,"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=\/wp\/v2\/posts\/877\/revisions\/878"}],"wp:attachment":[{"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=877"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=877"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/prayerlaputa.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=877"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}