原文地址:http://coach.iteye.com/blog/854996
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, 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,如不 进行额外的处理,将会出现这一问题。
其实定时任务都是开启的线程,如果能把开启的线程都设置成守护线程,那么也行。
相关推荐
在C#中编写多线程应用程序,简单! 菜鸟必备
多线程应用程序设计
多线程应用程序设计
嵌入式 Linux 应用程序开发 第9章多线程编程 华清远见
基于SOCKET和多线程的应用程序间通信技术的研究.pdf
锁定排序 3.6 线程优先级 3.7 监控程序线程 3.8 在应用程序中加入线程 3.9 线程控制 3.9.1 线程启动 3.9.2 线程休眠 3.9.3 线程挂起 3.9.4 线程恢复 3.9.5 线程停止 3.9.6...
2.2多线程应用程序设计,适合初学者,相当可以的啊
编写简单的HTTP 1.0客户端/服务器程序:.编写多线程Web服务器:编写简单的RMI程序 包含实验PPT 实验报告
基于Html5的web线程
安全的编写多线程的_Java_应用程序安全的编写多线程的_Java_应用程序
教你怎么开发线程安全的SpringWeb应用.
用PB编写多线程应用程序,使程序更有效率
用Pro*C开发多线程应用程序 (注:本文来自Pro*C/C++ Precompiler Programmer's Guide Release 8.1.5) 如果你的操作系统不支持线程,本文暂不适合你。本文包含以下几个部分: n 什么是多线程? n Pro*C中的运行时上...
另一个原因在于JSP支持强大的Web应用程序开发模式,它可以把外观呈现与处理过程分隔开来,使得擅长图形制作、布局的网页设计师与精通服务器端技术(例如多线程,资源池, 数据库和高速缓存)的程序员能够协调地工作...
在计算机系统正常运行过程中用户从客户端启动加载自己的应用程序时常常希望程序在服务进程中不会被用户关闭掉程序,采用钩子函数拦截系统消息是一种解决思路和方法,但会受到系统的制约。可以利用主程序即主进程来构造...
示例描述:使用Visual C++ 6.0开发基于多线程的Windows应用程序。 Race 多线程实现百米赛跑模拟。
本教程是继使用HttpClient调用Web API只有的补充教程,主要讲解了如何在WPF中异步调用Web API且不阻塞主线程。
VC++6.0多线程技术在端口扫描程序中的应用C++源代码程序小实例
Java Thread API 允许程序员编写具有多处理机制优点的应用程序,在后台处理任务的同时保持用户所需的交互感。Alex Roetter 介绍了 Java Thread API,并概述多线程可能引起的问题以及常见问题的解决方案。