tomcat-quartz 集成的时候 关闭tomcat异常处理

在tomcat7+quartz1.8/1.7 + spring3.0.5做定时任务的时候 , 当关闭tomcat时会发现如下异常:

[java]  view plain copy
  1.         ar 272013 6:05:35 PM org.apache.coyote.AbstractProtocol pause  
  2. INFO: Pausing ProtocolHandler ["http-nio-8082"]  
  3. Mar 272013 6:05:35 PM org.apache.catalina.core.StandardService stopInternal  
  4. INFO: Stopping service Catalina  
  5. Mar 272013 6:05:35 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  
  6. SEVERE: The web application [/****] appears to have started a thread named [startQuertz_Worker-1] buthas       failed to stop it. This is very likely to create a memory leak.  
  7. Mar 272013 6:05:35 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  
  8. SEVERE: The web application [/****] appears to have started a thread named [startQuertz_Worker-2] buthas  failed to stop it. This is very likely to create a memory leak.  
  9. Mar 272013 6:05:35 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  
  10. SEVERE: The web application [/****] appears to have started a thread named [startQuertz_Worker-3] buthas   failed to stop it. This is very likely to create a memory leak.  
  11. Mar 272013 6:05:35 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads  



首先怀疑线程泄漏 , 依各位前辈的经验建议 , 修改quartz的配置:

       

[html]  view plain copy
  1. <bean id="startQuertz" lazy-init="false" autowire="no"  
  2.     class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  3.     <property name="triggers">  
  4.         <list>                  
  5.               
  6.         </list>  
  7.     </property>  
  8.     <property name="quartzProperties">    
  9.        <props>    
  10.            <prop key="org.quartz.scheduler.instanceName">buy_it_now</prop>  
  11.            <prop key="org.quartz.threadPool.threadCount">2</prop>    
  12.            <prop key="org.quartz.plugin.shutdownhook.class">org.quartz.plugins.management.ShutdownHookPlugin</prop>  
  13.            <prop key="org.quartz.plugin.shutdownhook.cleanShutdown">true</prop>  
  14.            <prop key="org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread">true</prop>  
  15.        </props>    
  16.    </property>    
未果 , 以上配置只是设置了线程池的大小和在shutdown时进行清理 , 结果在老外的网站上发现了解决办法。

 

日志warn可能线程泄漏 ,但事实并非如此(本人没考证) , 只是tomcat在shutdown做清理工作的时候没能等待quartz完成cleanShutdown !就是tomcat太心急了 , 说 “quartz  , 我关门了 , 你走吧!” , 还没等quartz反应过来,

就要关大门 , 这时发现 “quartz , 你怎么还在这儿呀!”。 解决的办法简单:自己实现一个ServletContextListener ,

在contextDestroyed的时候主动调用quartz schedular的shutdown方法  ,并且主线程sleep一会儿 , 上例子:


     

[java]  view plain copy
  1. public class QuartzContextListener implements ServletContextListener {  
  2.   
  3.     /* 
  4.      * 测试代码写得随便 
  5.      *  
  6.      * @seejavax.servlet.ServletContextListener#contextDestroyed(javax.servlet. 
  7.      * ServletContextEvent) 
  8.      */  
  9.     @Override  
  10.     public void contextDestroyed(ServletContextEvent arg0) {  
  11.         WebApplicationContext webApplicationContext = (WebApplicationContext) arg0  
  12.                 .getServletContext()  
  13.                 .getAttribute(  
  14.                         WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);  
  15.         org.quartz.impl.StdScheduler startQuertz = (org.quartz.impl.StdScheduler) webApplicationContext  
  16.                 .getBean("startQuertz");  
  17.         if(startQuertz != null) {  
  18.             startQuertz.shutdown();  
  19.         }  
  20.         try {  
  21.             Thread.sleep(1000);  
  22.         } catch (InterruptedException e) {  
  23.             e.printStackTrace();  
  24.         }  
  25.     }  
  26.   
  27.     /* 
  28.      * (non-Javadoc) 
  29.      *  
  30.      * @see 
  31.      * javax.servlet.ServletContextListener#contextInitialized(javax.servlet 
  32.      * .ServletContextEvent) 
  33.      */  
  34.     @Override  
  35.     public void contextInitialized(ServletContextEvent arg0) {  
  36. <span style="white-space:pre">      </span>//不做任何事情  
  37.     }  
  38.   
  39. }  

  别忘了web.xml中添加起! 结束

报错内容如下 [INFO][2018-08-24 21:30:11] com.alibaba.druid.pool.DruidDataSource.close(DruidDataSource.java:1825) {dataSource-1} closed 24-Aug-2018 21:30:11.702 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) java.lang.Thread.run(Thread.java:745) 24-Aug-2018 21:30:11.702 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-3-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) java.lang.Thread.run(Thread.java:745) 24-Aug-2018 21:30:11.703 警告 [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-4-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: sun.misc.Unsafe.park(Native Method) java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442) java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) java.lang.Thread.run(Thread.java:745) 24-Aug-2018 21:30:11.705 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-apr-8080"] 24-Aug-2018 21:30:11.773 信息 [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-apr-8009"] 24-Aug-2018 21:30:11.825 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-apr-8080"] 24-Aug-2018 21:30:11.826 信息 [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-apr-8009"] ``` ``` 根据网上的解决方法,我已经关闭了定时任务Scheduler,关闭了开启定时任务的线程池,也关闭了数据源。为什么还是报错? 我的代码 package com.yz.robot.spring; import com.yz.robot.mcore.utils.SpringContextUtils; import com.yz.robot.mquartz.service.ScheduleJobService; import com.yz.robot.mquartz.service.impl.ScheduleJobServiceImpl; import com.yz.robot.mquartz.utils.ScheduleJob; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.impl.StdSchedulerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import java.sql.Driver; import java.sql.DriverManager; import java.util.Enumeration; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutorService; public class QuartzJobListener implements ServletContextListener { @Autowired private ScheduleJob scheduleJob; @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("--------------开始-------"); } @Override public void contextDestroyed(ServletContextEvent sce){ WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext()); if (webApplicationContext != null){ Object scheduleJobServiceImpl = webApplicationContext.getBean("scheduleJob"); System.out.println("-------------------------2"); System.out.println(scheduleJobServiceImpl !=null); }else { System.out.println("获取应用程序上下文失败!"); } try { Scheduler defaultScheduler = StdSchedulerFactory.getDefaultScheduler(); System.out.println("-------------------------2"); System.out.println(defaultScheduler.isShutdown()); defaultScheduler.shutdown(true); Thread.sleep(1000); System.out.println(defaultScheduler.isShutdown()); ScheduleJob scheduleJob = (ScheduleJob) SpringContextUtils.getBean("scheduleJob"); //scheduleJobServiceImpl ExecutorService service = scheduleJob.getService(); System.out.println("-------------------------3"); System.out.println(service!=null); System.out.println(service.isShutdown()); List<Runnable> runnables = service.shutdownNow(); System.out.println(service.isShutdown()); Thread.sleep(1000); System.out.println("-------------------------4"); Enumeration<Driver> drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()){ Driver driver = drivers.nextElement(); DriverManager.deregisterDriver(driver); System.out.println("又注销了一个driver"+driver.toString()); } } catch (Exception e) { e.printStackTrace(); } } } 大佬们帮帮我吧??? ```
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页