如何优雅的关闭 Java线程池
如何優(yōu)雅的關(guān)閉 Java線程池
簡介 在開發(fā)中使用線程池去執(zhí)行異步任務(wù)是比較普遍的操作 ,然而雖然有些異步操作我們并不十分要求可靠性和實時性,但總歸業(yè)務(wù)還是需要的。如果在每次的服務(wù)發(fā)版過程中,我們不去介入線程池的停機邏輯,那么很有可能就會造成線程池中隊列的任務(wù)還未執(zhí)行完成,自然就會造成數(shù)據(jù)的丟失 。
探究
注意,本文所有前提是對進程進行下線時使用的是kill -15
我們知道Spring已經(jīng)實現(xiàn)了自己的優(yōu)雅停機方案 ,詳細請參考o(jì)rg.springframework.context.support.AbstractApplicationContext#registerShutdownHook,然后主要看調(diào)用的org.springframework.context.support.AbstractApplicationContext#doClose, 在這個方法里定義了容器銷毀的執(zhí)行順序
protected void doClose() { // Check whether an actual close attempt is necessary... if (this.active.get() && this.closed.compareAndSet(false, true)) { if (logger.isDebugEnabled()) { logger.debug("Closing " + this); } LiveBeansView.unregisterApplicationContext(this); try { // Publish shutdown event. publishEvent(new ContextClosedEvent(this)); } catch (Throwable ex) { logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex); } // Stop all Lifecycle beans, to avoid delays during inpidual destruction. if (this.lifecycleProcessor != null) { try { this.lifecycleProcessor.onClose(); } catch (Throwable ex) { logger.warn("Exception thrown from LifecycleProcessor on context close", ex); } } // Destroy all cached singletons in the context's BeanFactory. destroyBeans(); // Close the state of this context itself. closeBeanFactory(); // Let subclasses do some final clean-up if they wish... onClose(); // Reset local application listeners to pre-refresh state. if (this.earlyApplicationListeners != null) { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // Switch to inactive. this.active.set(false); } }我們先主要關(guān)注下destroyBeans這個方法 ,看bean的銷毀邏輯是什么 ,然后看到了下面的一個bean的銷毀順序邏輯,具體方法在org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingletons
private final MapdisposableBeans = new LinkedHashMap<>(); public void destroySingletons() { if (logger.isTraceEnabled()) { logger.trace("Destroying singletons in " + this); } synchronized (this.singletonObjects) { this.singletonsCurrentlyInDestruction = true; } String[] disposableBeanNames; synchronized (this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1; i >= 0; i--) { destroySingleton(disposableBeanNames[i]); } this.containedBeanMap.clear(); this.dependentBeanMap.clear(); this.dependenciesForBeanMap.clear(); clearSingletonCache(); } 可以看到最至關(guān)重要的就是一個屬性disposableBeans,這個屬性是一個LinkedHashMap , 因此屬性是有序的