2017年11月

在应用里经常都有用到在后台跑定时任务的需求。举个例子,比如需要在服务后台跑一个定时任务来进行非实时计算,清除临时数据、文件等。在本文里,我会给大家介绍3种不同的实现方法:

  • 普通thread实现
  • TimerTask实现
  • ScheduledExecutorService实现

普通thread

这是最常见的,创建一个thread,然后让它在while循环里一直运行着,通过sleep方法来达到定时任务的效果。这样可以快速简单的实现,代码如下:

用Timer和TimerTask

上面的实现是非常快速简便的,但它也缺少一些功能。

用Timer和TimerTask的话与上述方法相比有如下好处:

  • 当启动和去取消任务时可以控制
  • 第一次执行任务时可以指定你想要的delay延迟时间

在实现时,Timer类可以调度任务,TimerTask则是通过在run()方法里实现具体任务。

Timer实例可以调度多任务,它是线程安全的。

当Timer的构造器被调用时,它创建了一个线程,这个线程可以用来调度任务:

ScheduledExecutorService

ScheduledExecutorService是从Java SE 5的java.util.concurrent里,做为并发工具类被引进的,这是最理想的定时任务实现方式。

相比于上两个方法,它有以下好处:

  • 相比于Timer的单线程,它是通过线程池的方式来执行任务的
  • 可以很灵活的去设定第一次执行任务delay时间
  • 提供了良好的约定,以便设定执行的时间间隔

我们通过ScheduledExecutorService#scheduleAtFixedRate展示这个例子,通过代码里参数的控制,首次执行加了delay时间:

Servlet 生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 通过调用 init () 方法进行初始化。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 通过调用 destroy() 方法终止(结束)。
  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

现在让我们详细讨论生命周期的方法。

init() 方法

init 方法被设计成只调用一次。它在第一次创建 Servlet 时被调用,在后续每次用户请求时不再调用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一样。

Servlet 创建于用户第一次调用对应于该 Servlet 的 URL 时,但是您也可以指定 Servlet 在服务器第一次启动时被加载。

当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。

init 方法的定义如下:

public void init() throws ServletException {
  // 初始化代码...
}

service() 方法

service() 方法是执行实际任务的主要方法。Servlet 容器(即 Web 服务器)调用 service() 方法来处理来自客户端(浏览器)的请求,并把格式化的响应写回给客户端。

每次服务器接收到一个 Servlet 请求时,服务器会产生一个新的线程并调用服务。service() 方法检查 HTTP 请求类型(GET、POST、PUT、DELETE 等),并在适当的时候调用 doGet、doPost、doPut,doDelete 等方法。

下面是该方法的特征:

public void service(ServletRequest request, 
                    ServletResponse response) 
      throws ServletException, IOException{
}

service() 方法由容器调用,service 方法在适当的时候调用 doGet、doPost、doPut、doDelete 等方法。所以,您不用对 service() 方法做任何动作,您只需要根据来自客户端的请求类型来重载 doGet() 或 doPost() 即可。

doGet() 和 doPost() 方法是每次服务请求中最常用的方法。下面是这两种方法的特征。

doGet() 方法

GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。

public void doGet(HttpServletRequest request,
                  HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

doPost() 方法

POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。

public void doPost(HttpServletRequest request,
                   HttpServletResponse response)
    throws ServletException, IOException {
    // Servlet 代码
}

destroy() 方法

destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。

在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。destroy 方法定义如下所示:

  public void destroy() {
    // 终止化代码...
  }

1:J2SE

面向对象-封装、继承、多态、内存的分析、递归、集合类、泛型、自动打包与解包、Annotation、IO 、多线程、线程同步 、TCP/UDP 、AWT、事件模型、匿名类、正则表达式、反射机制。

2:数据库(Oracle或者MySQL)

SQL语句、多表连接,内外连接, 子查询等、管理表、视图、索引、序列、约束等、树状结构存储、存储过程、触发器、数据库设计三范式。

3:JDBC

JDBC基础、连接池 、树状结构存储与展现、DataSource & RowSet 、JDBC连接Oracle及MySQL。

4:HTML、CSS、javascript(做后台程序员了解即可)

html、css、javascript基础语法、JavaScript Form判断、Dom编程基础(事件处理等)、JS常用效果如TreeView、下拉联动等、JS学习方法 、JS调试方法 DreamWeaver初步(建立HTML、Table、Form、CSS)等。

5:Servlet & JSP

tomcat基础 、servlet基础 、web.xml配置基础、web application的结构 、servlet生命周期request response等常用方法 、ServletContext类 、HTTP协议基础(GET POST)Cookie 、Session 、Application、 JSP的几种语法(包括JSTL等)注意在项目中练习,不要拘泥于语法细节而裹步不前。

6:Struts

多层架构理论 、Model 1 and Model 2 、Struts基本概念 、MVC、Action与业务逻辑类的关系 、在Struts与JSP之间传递数据、Struts处理流程(控制流) 、Struts TagLib(了解常用的) 、JSTLActionForm、字段收集、上传文件 、类型转换 、DTO 、动态Action Form 、验证框架、ActionForward 转发与重定向 、动态生成ActionForward 、全局与局部ActionForward 、Action Forward Scope、UnknownActionMapping 、Action的线程安全 、I18N 、如何切换语言环境、Struts异常处理机制 程序处理 自动处理 自定义异常处理器Struts的多模块配置。

7:XML

(XML/XSL、XSLT/DTD、SCHEMA等基础的概念、关于Java的编程可以暂时扔在一边)。

8:Hibernate

OR Mapping原理 、Hibernate基础开发步骤 、Hibernate基本接口(重点Session)、普通属性映射 、关联关系映射 Native SQL 、inverse lazy cascade 、继承关系映射 、HQL 、性能优化 一级缓存 二级缓存 查询缓存、事务与并发 悲观锁、乐观锁 、OpenSessionInView 、CurrentSession (至于JTA、联合主键、自然主键、动态主键、Any类型 Creteria Queries Intercepter and Event 自定义类型等,可以暂时扔在一边)。

9:Spring

IOC/DI 、Spring配置、Spring架构 、AOP及Spring AOP 、声明式事务(AOP)、Spring + Hibernate Spring支持Web 、Scope(其他的Spring模块对于自学来说可以暂时扔在一边)。

10:EJB3.0

J 2EE架构基础(JTA JMS等) 、EJB基础(地位及基本理论、分类等)、Annotation 、Ant编译与部署EJB 、Session Bean 、EJB的依赖注入 、Persistence API。

下面还加一个学习流程图:

2017——8年阿里JAVA大神,教你如何正确的学习JAVA(新手必看)

我确确实实希望本文可以帮助你提升技术水平。那些,感觉学的好难,甚至会令你沮丧的人,别担心,我认为,如果你愿意试一试本文介绍的几点,会向前迈进,克服这种感觉。这些要点也许对你不适用,但你会明确一个重要的道理:接受自己觉得受困这个事实是摆脱这个困境的第一步。