Servlet中多个计划任务调度管理的实现

同学在做一个Java web项目时遇到了点麻烦。问题是这样的,他需要在后台运行一些计划任务,通过Timer来实现的。同时又需要通过Servlet来控制指定的计划任务运行或者停止运行。这个问题看似简单,实际上涉及了一些Servlet生命周期的知识以及变量作用域的知识。

首先看Timer应该在什么时候创建。在的doGet()中创建显然是不行的,因为doGet作用在用户访问的那个线程,这里创建的Timer无法通过cancle停止,因为再一次访问Servlet的时候会创建一个新的线程,在这个新的线程中是无法调用之前线程创建的Timer的。所以应该把Timer作为Servlet的一个成员,这样就可以在不同的线程中访问Timer这个示例了。

但是问题又来了,由于有多个计划任务,创建每个计划任务时调用的是同一个Timer实例的schedule()方法,当调用cancle()方法时,所有的计划任务都会撤销。于是我在Servletz中创建了一个Map来将多个Timer与特定的key绑定,为每一个计划任务单独创建一个Timer,这样就可以分别撤销计划任务了。

以下是我写的示例代码:

package sample;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyTimer extends HttpServlet {
    private static final long serialVersionUID = 1L;
    Map map;

    public MyTimer() {
        super();
        map = new HashMap();
    }

    void setTimer(String key) {
        Timer t = new Timer();
        map.put(key, t);
    }

    void removeTimer(String key) {
        if (map.containsKey(key)) {
            map.get(key).cancel();
            map.remove(key);
        }
    }

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        String s;
        String t;
        s=request.getParameter("s");
        t=request.getParameter("t");
        if(s==null || t==null){
            response.getWriter().println("Ready");
        }else{
            if (t.equals("1")) {
                setTimer(s);
                map.get(s).schedule(new MyTick(s), new Date(), 1000);
                response.getWriter().println("timer "+s+" on!");
            } else {
                removeTimer(s);
                response.getWriter().println("timer "+s+" off!");
            }
        }
        if(!map.isEmpty()){
            for(String k:map.keySet()){
                response.getWriter().println(k+" is running");
            }
        }
    }

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
    }

}

class MyTick extends TimerTask {
    boolean isRun = false;
    String id;

    MyTick(String id) {
        super();
        this.id = id;
    }

    public void run() {
        if (!isRun) {
            isRun = true;
            System.out.println(this.id + ":" + (new Date().toString()));
            isRun = false;
        }
    }
}

在服务器上运行这个servlet,在浏览器中访问“http://path-to/servlet?t=a&s=1”,可以看到命令行中看到计时器a在运行,再输入“http://path-to/servlet?t=b&s=1”,可以看到计时器a和b同时在运行,然后访问“http://path-to/servlet?t=a&s=0”,可以看到计时器a停止运行。

至此,这个问题已经得到解决。

《Servlet中多个计划任务调度管理的实现》有2个想法

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Time limit is exhausted. Please reload CAPTCHA.