ThreadPoolExecutor 线程销毁源码分析

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"线程池在开发中使用非常频繁,在面试中也是高频面试点,最近翻看源码,有一些心得分享下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"线程池回收线程的大致流程:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1、调用线程池的 shutdown() 方法或者 shutdownNow() 方法;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2、主线程修改线程池的状态:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"shutdown() -> SHUTDOWN","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" shutdownNow() -> STOP","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"3、中断线程池中所有线程;中断一些阻塞的线程,让线程正常结束执行;","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"4、每个 work 线程在获取任务的时候 getTask(), 校验当前线程池的状态,如果线程池状态已经被修改为非 RUNNING状态,时机合适,work线程退出","attrs":{}},{"type":"text","text":";","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"详情请看下面的源码注释:","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1. 线程池状态:","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"// 线程池初始状态\nprivate static final int RUNNING = -1 << COUNT_BITS;\n// 调用 shutdown() 方法后线程池状态\nprivate static final int SHUTDOWN = 0 << COUNT_BITS;\n// 调用 shutdownNow() 方法后线程池状态\nprivate static final int STOP = 1 << COUNT_BITS;\n// 在 TERMINATED 前的一个过渡状态,用处不多\nprivate static final int TIDYING = 2 << COUNT_BITS;\n// 线程池终止状态\nprivate static final int TERMINATED = 3 << COUNT_BITS;","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.1 shutdown 方法","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public void shutdown() {\n final ReentrantLock mainLock = this.mainLock;\n mainLock.lock();\n try {\n // 校验调用 shutdown() 线程是否可以操作此方法,校验被终止任务的线程(works)是否可以被终止\n checkShutdownAccess();\n // CAS 修改线程池运行状态为:SHUTDOWN \n advanceRunState(SHUTDOWN);\n // 中断所有工作线程\n interruptIdleWorkers();\n // hook for ScheduledThreadPoolExecutor\n onShutdown(); \n } finally {\n mainLock.unlock();\n }\n \t// 尝试中断线程池\n tryTerminate();\n}","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2.2 shutdownNow","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public List shutdownNow() {\n List tasks;\n final ReentrantLock mainLock = this.mainLock;\n mainLock.lock();\n try {\n // 校验调用 shutdownNow() 线程是否可以操作此方法,校验被终止任务的线程(works)是否可以被终止\n checkShutdownAccess();\n // CAS 修改线程池运行状态为:STOP \n advanceRunState(STOP);\n // 中断所有工作线程\n interruptWorkers();\n // 移除队列中的任务,并返回被移除的任务\n tasks = drainQueue();\n } finally {\n mainLock.unlock();\n }\n tryTerminate();\n return tasks;\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3. interruptIdleWorkers","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private void interruptIdleWorkers(boolean onlyOne) {\n final ReentrantLock mainLock = this.mainLock;\n mainLock.lock();\n try {\n // 遍历 works 工作线程集合,中断每个阻塞获取任务的线程,让这些线程执行完当前逻辑,退出 run() 方法\n for (Worker w : workers) {\n Thread t = w.thread;\n if (!t.isInterrupted() && w.tryLock()) {\n try {\n t.interrupt();\n } catch (SecurityException ignore) {\n } finally {\n w.unlock();\n }\n }\n if (onlyOne)\n break;\n }\n } finally {\n mainLock.unlock();\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4. tryTerminate()","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":" final void tryTerminate() {\n for (;;) {\n int c = ctl.get();\n // 线程池 RUNNING 退出\n // 线程池 TIDYING 退出\n // 线程池 SHUTDOWN 并且 队列不为空(还有没处理完的任务)退出\n if (isRunning(c) ||\n runStateAtLeast(c, TIDYING) ||\n (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))\n return;\n // 还有活跃的线程,中断一个\n if (workerCountOf(c) != 0) { // Eligible to terminate\n interruptIdleWorkers(ONLY_ONE);\n return;\n }\n\n final ReentrantLock mainLock = this.mainLock;\n mainLock.lock();\n try {\n if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {\n try {\n terminated();\n } finally {\n ctl.set(ctlOf(TERMINATED, 0));\n termination.signalAll();\n }\n return;\n }\n } finally {\n mainLock.unlock();\n }\n // else retry on failed CAS\n }\n }","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5.Work 类:工作线程","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":" private final class Worker extends AbstractQueuedSynchronizer implements Runnable{\n private static final long serialVersionUID = 6138294804551838833L;\n\n /** 线程池里的工作线程,该线程在创建 Work 对象的时候传入 */\n final Thread thread;\n /** 工作线程创建好后,执行的第一个任务 */\n Runnable firstTask;\n /** 工作线程执行任务数量 */\n volatile long completedTasks;\n\n /**\n * 创建一个Work线程,指定第一个被执行的任务\n */\n Worker(Runnable firstTask) {\n setState(-1); \n this.firstTask = firstTask;\n this.thread = getThreadFactory().newThread(this);\n }\n\n /** work 线程启动后,执行run方法,直到线程退出 */\n public void run() {\n runWorker(this);\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"6. runWorker","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"final void runWorker(Worker w) {\n Thread wt = Thread.currentThread();\n // task 默认为创建work时候指定的第一个任务\n Runnable task = w.firstTask;\n w.firstTask = null;\n w.unlock(); // allow interrupts\n boolean completedAbruptly = true;\n try {\n \n /**\n * 1、第一个任务不为 null,先执行第一个任务,往后循环的从任务队列里取任务执行\n * 2、只有 getTask() 返回null的时候,才会退出循环\n */\n while (task != null || (task = getTask()) != null) {\n w.lock();\n /** double check\n * 防止线程池已经被设置成 STOP 状态后,部分线程响应中断失败,\n * 这个地方再重新校验并设置下当前线程的中断状态\n */\n if ((runStateAtLeast(ctl.get(), STOP) ||\n (Thread.interrupted() &&\n runStateAtLeast(ctl.get(), STOP))) &&\n !wt.isInterrupted())\n wt.interrupt();\n try {\n // 默认没有实现,可以在子类中扩展\n beforeExecute(wt, task);\n Throwable thrown = null;\n // 执行任务\n task.run();\n // 省略部分 try-catch 代码\n } finally {\n task = null;\n // 当前线程执行任务数累计\n w.completedTasks++;\n w.unlock();\n }\n }\n // 当 getTask() 为null的时候可以走到这一步\n completedAbruptly = false;\n } finally {\n // getTask() 为 null,任务被执行完了,线程退出\n processWorkerExit(w, completedAbruptly);\n }","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#F5222D","name":"red"}}],"text":"7. getTask","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private Runnable getTask() {\n // 记录上次从任务队列获取任务是否超时\n boolean timedOut = false; \n // 循环遍历,直到获取到任务或者被中断\n for (;;) {\n // 线程池线程数量\n int c = ctl.get();\n // 线程池状态\n int rs = runStateOf(c);\n\t\t\n // 如果线程池状态:RUNNING(-1)|SHUTDOWN(0)|STOP(1)|TIDYING(2)|TERMINATED(3)\n // 两种情况:\n // 1、如果是 STOP 以后状态(不用管任务队列里是否有任务未执行完),线程总数减1,立即返回 null;\n // 2、在上面的情况之后,如果是 SHUTDOWN 以后的状态 && 任务队列为空(因为要等任务执行完),线程总数减1,并立即返回 null;\n if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {\n decrementWorkerCount();\n return null;\n }\n int wc = workerCountOf(c);\n /**\n * 1、allowCoreThreadTimeOut:是否让核心线程空闲回收,默认false\n * 2、当前线程池中线程数是否大于核心线程数\n */\n boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;\n\t\t\n /** \n * 在线程池中'还有线程'或者'任务队列没有任务'的情况下:\n * 1、如果线程池中的线程数,大于设置的最大线程数,必须停止当前线程;\n * 2、在当前线程获取任务超时(说明队列里没有任务可以被执行):\n * (1)而核心线程允许超时回收,则回收当前线程(因为核心线程和线程池中其他线程没有特殊的标记,\n * 回收了就回收了,如果下次线程池中线程不足,再新建一个线程扮演核心线程的角色即可);\n * (2) 当前线程总数超过了核心线程数,而现在又没有任务需要执行,自然回收当前线程;\n */\n if ((wc > maximumPoolSize || (timed && timedOut))\n && (wc > 1 || workQueue.isEmpty())) {\n if (compareAndDecrementWorkerCount(c))\n return null;\n continue;\n }\n try {\n /** \n * 1、如果允许核心线程空闲退出 或者 当前线程数大于核心线程数的情况下:\n * \t\tpoll() 设置获取任务的阻塞时间,超时后,返回 null,当循环执行到上面的两处校验处,返回 null 退出;\n * 2、take()阻塞式获取任务,知道任务队列有可被执行任务为止;\n */\n Runnable r = timed ?\n workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :\n workQueue.take();\n if (r != null)\n return r;\n // 超时后仍未获取到任务\n timedOut = true;\n } catch (InterruptedException retry) {\n timedOut = false;\n }\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"8. processWorkerExit","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"private void processWorkerExit(Worker w, boolean completedAbruptly) {\n if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted\n decrementWorkerCount();\n final ReentrantLock mainLock = this.mainLock;\n mainLock.lock();\n try {\n // 统计每个线程完成的任务数\n completedTaskCount += w.completedTasks;\n // 从线程池(set)中移除当前线程\n workers.remove(w);\n } finally {\n mainLock.unlock();\n }\n\t// 修改线程池中断状态\n tryTerminate();\n\n int c = ctl.get();\n /**\n * 如果当前线程池的状态不是 STOP,说明当前状态是 RUNNING 或者 SHUTDOWN,\n * 这个时候要保证线程池内有必要的线程去执行队列的任务\n */\n if (runStateLessThan(c, STOP)) {\n if (!completedAbruptly) {\n int min = allowCoreThreadTimeOut ? 0 : corePoolSize;\n // 如果当前线程数为0,但是任务队列里又有任务需要被执行,必须调整线程数\n if (min == 0 && ! workQueue.isEmpty())\n min = 1;\n if (workerCountOf(c) >= min)\n return; // replacement not needed\n }\n // 给线程池新增一个线程,保证任务被执行完\n addWorker(null, false);\n }\n}","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章