Web应用程序中调度器的启动和关闭问题
2014-10-15 16:52
162 查看
我们知道静态变量是ClassLoader级别的,如果Web应用程序停止,这些静态变量也会从JVM中清除。但是线程则是JVM级别的,如果你在Web 应用中启动一个线程,这个线程的生命周期并不会和Web应用程序保持同步。也就是说,即使你停止了Web应用,这个线程依旧是活跃的。正是因为这个很隐晦 的问题,所以很多有经验的开发者不太赞成在Web应用中私自启动线程。
如果我们手工使用JDK Timer(Quartz的Scheduler),在Web容器启动时启动Timer,当Web容器关闭时,除非你手工关闭这个Timer,否则Timer中的任务还会继续运行!
下面通过一个小例子来演示这个“诡异”的现象,我们通过ServletContextListener在Web容器启动时创建一个Timer并周期性地运行一个任务:
Java代码
//代码清单StartCycleRunTask:容器监听器
package com.baobaotao.web;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class StartCycleRunTask implements ServletContextListener ...{
private Timer timer;
public void contextDestroyed(ServletContextEvent arg0) ...{
// ②该方法在Web容器关闭时执行
System.out.println("Web应用程序启动关闭...");
}
public void contextInitialized(ServletContextEvent arg0) ...{
//②在Web容器启动时自动执行该方法
System.out.println("Web应用程序启动...");
timer = new Timer();//②-1:创建一个Timer,Timer内部自动创建一个背景线程
TimerTask task = new SimpleTimerTask();
timer.schedule(task, 1000L, 5000L); //②-2:注册一个5秒钟运行一次的任务
}
}
class SimpleTimerTask extends TimerTask ...{//③任务
private int count;
public void run() ...{
System.out.println((++count)+"execute task..."+(new Date()));
}
}
在web.xml中声明这个Web容器监听器:<?xml version="1.0" encoding="UTF-8"?>
<web-app>
…
<listener>
<listener-class>com.baobaotao.web.StartCycleRunTask</listener-class>
</listener>
</web-app>
在Tomcat中部署这个Web应用并启动后,你将看到任务每隔5秒钟执行一次。
运行一段时间后,登录Tomcat管理后台,将对应的Web应用(chapter13)关闭。
转到Tomcat控制台,你将看到虽然Web应用已经关闭,但Timer任务还在我行我素地执行如故——舞台已经拆除,戏子继续表演:
我们可以通过改变清单StartCycleRunTask的代码,在contextDestroyed(ServletContextEvent arg0)中添加timer.cancel()代码,在Web容器关闭后手工停止Timer来结束任务。
Spring为JDK Timer和Quartz Scheduler所提供的TimerFactoryBean和SchedulerFactoryBean能够和Spring容器的生命周期关联,在 Spring容器启动时启动调度器,而在Spring容器关闭时,停止调度器。所以在Spring中通过这两个FactoryBean配置调度器,再从
Spring IoC中获取调度器引用进行任务调度将不会出现这种Web容器关闭而任务依然运行的问题。而如果你在程序中直接使用Timer或Scheduler,如不 进行额外的处理,将会出现这一问题。
如果我们手工使用JDK Timer(Quartz的Scheduler),在Web容器启动时启动Timer,当Web容器关闭时,除非你手工关闭这个Timer,否则Timer中的任务还会继续运行!
下面通过一个小例子来演示这个“诡异”的现象,我们通过ServletContextListener在Web容器启动时创建一个Timer并周期性地运行一个任务:
Java代码
//代码清单StartCycleRunTask:容器监听器
package com.baobaotao.web;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class StartCycleRunTask implements ServletContextListener ...{
private Timer timer;
public void contextDestroyed(ServletContextEvent arg0) ...{
// ②该方法在Web容器关闭时执行
System.out.println("Web应用程序启动关闭...");
}
public void contextInitialized(ServletContextEvent arg0) ...{
//②在Web容器启动时自动执行该方法
System.out.println("Web应用程序启动...");
timer = new Timer();//②-1:创建一个Timer,Timer内部自动创建一个背景线程
TimerTask task = new SimpleTimerTask();
timer.schedule(task, 1000L, 5000L); //②-2:注册一个5秒钟运行一次的任务
}
}
class SimpleTimerTask extends TimerTask ...{//③任务
private int count;
public void run() ...{
System.out.println((++count)+"execute task..."+(new Date()));
}
}
在web.xml中声明这个Web容器监听器:<?xml version="1.0" encoding="UTF-8"?>
<web-app>
…
<listener>
<listener-class>com.baobaotao.web.StartCycleRunTask</listener-class>
</listener>
</web-app>
在Tomcat中部署这个Web应用并启动后,你将看到任务每隔5秒钟执行一次。
运行一段时间后,登录Tomcat管理后台,将对应的Web应用(chapter13)关闭。
转到Tomcat控制台,你将看到虽然Web应用已经关闭,但Timer任务还在我行我素地执行如故——舞台已经拆除,戏子继续表演:
我们可以通过改变清单StartCycleRunTask的代码,在contextDestroyed(ServletContextEvent arg0)中添加timer.cancel()代码,在Web容器关闭后手工停止Timer来结束任务。
Spring为JDK Timer和Quartz Scheduler所提供的TimerFactoryBean和SchedulerFactoryBean能够和Spring容器的生命周期关联,在 Spring容器启动时启动调度器,而在Spring容器关闭时,停止调度器。所以在Spring中通过这两个FactoryBean配置调度器,再从
Spring IoC中获取调度器引用进行任务调度将不会出现这种Web容器关闭而任务依然运行的问题。而如果你在程序中直接使用Timer或Scheduler,如不 进行额外的处理,将会出现这一问题。
相关文章推荐
- Web应用程序中调度器的启动和关闭问题
- Web应用程序中线程的启动和关闭问题
- Web应用程序中线程的启动和关闭问题
- 【opencv】应用程序无法正常启动(0xc000007b)。请单击“确定”关闭应用程序。问题解决方法
- web应用程序开发注意私自启动线程的问题
- Web应用程序中调度器的启动和关闭问题
- SpringBoot web demo项目启动后立马自动关闭问题解决办法
- Web应用程序中调度器的启动和关闭问题
- hudson jenkins 中build完web工程后启动jetty,tomcat等web容器后启动进程自动关闭的问题
- VS调试问题整理 :无法在Web服务器上启动调试。您不具备调试此应用程序的权限...
- 打开项目时提示如下错误:Visual Studio .NET 无法创建应用程序 。问题很可能是因为本地 Web 服务器上没有安装所需的组件
- 无法在Web服务器上启动调试。您不具备调试此应用程序的权限,此项目的URL位于Internet区域。
- 无法在Web服务器上启动调试。您不具备调试此应用程序的权限,此项目的URL位于Internet区域
- PHP在后台启动Microsoft Word、打开一个新文件、键入一些文本、保存该文件然后关闭应用程序
- 启动Linux 的时候实现oracle数据库与Tomcat web服务器与操作系统一同关闭与启动
- Oracle管理与维护.安装创建启动关闭数据库的常见问题(一)
- Visual Studio .NET 无法创建或打开应用程序。问题很可能是因为本地Web服务器上没有安装所需的组件。请运行Visual Studio .NET安装程序并
- vs.net2003中解决"无法在web服务器上启动调试"问题一例
- 解决“由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题”
- VS.net2005写的程序如何在没有.Net FrameWork的机器上运行 --解决“由于应用程序的配置不正确,应用程序未能启动,重新安装应用程序可能会纠正这个问题”(转载)