Web应用程序中调度器的启动和关闭问题

我们知道静态变量是ClassLoader级别的,如果Web应用程序停止,这些静态变量也会从JVM中清除。但是线程则是JVM级别的,如果你在Web 应用中启动一个线程,这个线程的生命周期并不会和Web应用程序保持同步。也就是说,即使你停止了Web应用,这个线程依旧是活跃的。正是因为这个很隐晦 的问题,所以很多有经验的开发者不太赞成在Web应用中私自启动线程。

如果我们手工使用JDK Timer(Quartz的Scheduler),在Web容器启动时启动Timer,当Web容器关闭时,除非你手工关闭这个Timer,否则Timer中的任务还会继续运行!

下面通过一个小例子来演示这个“诡异”的现象,我们通过ServletContextListener在Web容器启动时创建一个Timer并周期性地运行一个任务:
 
// 代码清单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, 
1000L5000L); //②-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,如不 进行额外的处理,将会出现这一问题。

来源:
http://java.e800.com.cn/articles/2007/426/1177524100389641841_1.html
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值