java Web定时器

来源:互联网 发布:淘宝乔丹六折是正品? 编辑:程序博客网 时间:2024/04/27 20:32

这个类最终功能是每天某个时间点(如每晚22点)执行某一功能.

首先介绍java定时器(java.util.Timer)有定时执行计划任务的功能,通过设定定时器的间隔时间,会自动在此间隔时间后执行预先安排好的任务(java.util. TimerTask)

如: 每隔一个小时执行任务 timer.schedule(TimerTask, 0, 60 * 60 * 1000);

    schedule方法的第一个参数是需要执行的任务,此类的类型为java.util.TimerTask,第二个参数为执行任务前等待时间,此处0表示不等待,第三个参数为间隔时间,单位为毫秒

由于我们希望当Web工程启动时,定时器能自动开始计时,这样在整个Web工程的生命期里,就会定时的执行任务,因此启动定时器的类不能是一般的类,此处用Servlet的监听器类来启动定时器,通过在配置文件里配置此监听器, 让其在工程启动时自动加载运行,存活期为整个Web工程生命期.

要运用Servlet侦听器需要实现javax.servlet.ServletContextListener接口,以下是类设计:



publicclass TimerListenerimplements ServletContextListener {

 

     privateTimertimer =null;

 

     private SampleTasksampleTask;

 

 

   

    @Override

    publicvoid contextDestroyed(ServletContextEvent event) {

        timer.cancel();

 

        event.getServletContext().log("定时器销毁");

 

 

 

    }

 

    @Override

    publicvoid contextInitialized(ServletContextEvent event) {

        timer =newTimer(true);

 

        sampleTasknewSampleTask(event.getServletContext());

 

        event.getServletContext().log("定时器已启动");

 

        timer.schedule(sampleTask, 0, 60 * 60 * 1000);

 

        event.getServletContext().log ("已经添加任务调度表");

 

    }

 

}

 

publicclass SampleTaskextends TimerTask {

 

   

    private ServletContextcontext;

   

    privatestaticbooleanisRunning = false;

     

    privatestaticbooleanflag = true;

     

    privatestaticfinalintC_SCHEDULE_HOUR = 15;

     

    public SampleTask(ServletContextcontext){

 

        this.context = context;

 

    }

   

    @Override

    publicvoid run() {

        Calendar cal = Calendar.getInstance();

         

          if (!isRunning) {

     

              if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY) && flag) {

                  isRunning =true;

                  context.log("开始执行指定任务");

 

                  //需要执行的代码

                

                  isRunning =false;

                  flag =false;

                  context.log("指定任务执行结束");

              }

          } else {

              context.log("上一次任务执行还未结束");

          }

     

          if(C_SCHEDULE_HOUR != cal.get(Calendar.HOUR_OF_DAY)){

     

              flag =true;

     

          }

    }

}
要使用此监听器需要在web.xml中配置,如下:
<listener>
  <listener-class>包路径.TimerListener</listener-class>
</listener>

这样在web工程启动时,就会自动启动此监听器.

 

 

JAVA中Timer定时器调度方法

java timer中的时间调度方法主要有:
schedule(TimerTask task, Date firstTime, long period)
          Schedules the specified task for repeated fixed-delay execution, beginning at the specified time.

但是如果此时的firstTime小于(时间落后于)当前时间,那么
task会立即执行,在调试的时候不方便,因为程序一启动就开始执行了,或许还没有到任务的触发点。

schedule(TimerTask task, long delay, long period)
          Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.

如果采用设置delay时间的方法,则可以进行处理。
比如:设置执行时间为每天的13:50,如果启动的时候时间已经过了13:35,那么应该在明天的13:35进行执行。此时可以这样处理:

Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 13);
        cal.set(Calendar.MINUTE, 35);
        //cal.add(Calendar.DAY_OF_MONTH, 1);
        Date date = new Date();
        date = cal.getTime();
       
        Date now = new Date();
        long interval = date.getTime() - now.getTime();
        //should exec in next day
        if (interval < 0) {
            cal.add(Calendar.DAY_OF_MONTH, 1);
            date = cal.getTime();
            interval = date.getTime() - now.getTime();
        }      
        System.out.println("the interval time is: " + interval);
        //the exec time interval is 2 secs.
        timer.schedule(echoTask, interval, 2 * 1000);
如果delay的时间为负数,会报异常,因此,Calendar添加一天。

 

 

JAVA WEB程序中添加定时器

//这是我的定时器类,用来定时执行某段任务;

  package com.my.time;

  import java.text.ParseException;

  import java.text.SimpleDateFormat;

  import java.util.Date;

  import java.util.Timer;

  public class BugXmlTimer {

  public   Timer timer;

  public void timerStart(){

  timer = new Timer();

  Date datetime=new Date();

  Date midnightDate=new Date();

  SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");

  SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

  try {

  midnightDate = sdf2.parse(sdf1.format(datetime)+" 23:00:00");

  } catch (ParseException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

  }

  long in=midnightDate.getTime()-datetime.getTime();

  System.out.println("before task");

  //立刻执行,然后每隔30s执行一次

  timer.schedule(new BugXmlTimerTask(), 0,30000);

  }

  public void timerStop(){

  if(timer!=null)

  timer.cancel();

  }

  public static void main(String[] args){

  BugXmlTimer myTimer=new BugXmlTimer();

  // TODO Auto-generated method stub

  myTimer.timerStart();

  }

  }

  //这是执行任务的类,即每隔一段时间要做的事情在这里

  package com.my.time;

  import java.util.TimerTask;

  public class BugXmlTimerTask extends TimerTask {

  @Override

  public void run() {

  System.out.print("run task");

  }

  }

  //以下是出发定时操作的类,该类实现了ServletContextListener

  public class MyTimerListener implements ServletContextListener {

  private BugXmlTimer mytimer = new BugXmlTimer ();

  public void contextInitialized(ServletContextEvent event) {

  mytimer.timerStart();

  }

  public void contextDestroyed(ServletContextEvent event) {

  mytimer.timerStop();

  }

  }

  然后在web.xml里部署一下,即可在程序启动后运行定时器了!

  <listener>

  <listener-class>com.my.time.MyTimerListener </listener-class>

  </listener>

 

 

Java 定时器退出解决方案

项目中用到了 Timer 每隔一段时间进行一些操作,现在发现有时候莫名其妙地挂在这个计时器上的操作都不做了,用“JConsole”查看其中的线程以后,发现这个定时器线程也不在了(定时器创建的时候带了名字Timer timer = new Timer("MyTimer"),所以直接能看到),由于日志太多,之前的日志已经找不到了,所以没有办法看是否是有异常发生以及发生在哪里。初步估计,是不是由于TimerTask 中有异常抛出,如果定时器中没有处理的话,可能就会出问题。所以看了一下 java.util.Timer 的代码:

  1. // 在 TimerThread 中执行任务
  2. Timer.java:101:TimerThread
  3. // TimerThread 的入口
  4. // 这里只有一个 try/finally,如果 mainloop 中有异常抛出的话,肯定就结束运行。
  5. Timer.java:503:TimerThread.run()
  6. // 主循环体,其中只抓住了 InterruptedException 异常,其他的仍然往外抛。
  7. Timer.java:518:TimerThread.mainloop()

从上面的代码可以看出,如果执行的任务中有其他任何运行时异常(RuntimeException)抛出,就必然导致定时器取消,也就是说挂在这个定时器上所有的人物都要被取消。明白了其内部处理机制,就要将其应用于实践,看如下例子:

  1. WrongTimerTask.java:
  2.  
  3. package org.supermmx.example.timer;
  4.  
  5. import java.util.Timer;
  6. import java.util.TimerTask;
  7.  
  8. /**
  9. * Wrong timer task.
  10. *
  11. * @author SuperMMX
  12. */
  13. public class WrongTimerTask extends TimerTask {
  14. private int count = 0;
  15.  
  16. public void run() {
  17. System.out.println(count);
  18. count ++;
  19. if (count == 3) {
  20. throw new NullPointerException("Test Exception");
  21. }
  22. }
  23.  
  24. public static void main(String[] args) {
  25. try {
  26. WrongTimerTask task = new WrongTimerTask();
  27. Timer timer = newTimer("TestTimer");
  28. timer.scheduleAtFixedRate(task, 0, 1000);
  29. } catch (Exception e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }

上述代码中,每隔一秒钟打印一个递增的数值,等于 3 的时候抛一个空指针异常,结果怎么样呢?整个程序全部就退出了,就因为其中唯一的线程“TestTimer”退出了。跟前面所说的问题一模一样,只不过项目中还有很多别的线程,所以主程序并未退出。

解决方法是什么呢?其实很简单,将 TimerTask 中整个 run() 方法 try 起来就可以了,保证它不再往外抛异常,代码如下:

  1. RightTimerTask.java:
  2.  
  3. package org.supermmx.example.timer;
  4.  
  5. import java.util.Timer;
  6. import java.util.TimerTask;
  7.  
  8. /**
  9. * Wrong timer task.
  10. *
  11. * @author SuperMMX
  12. */
  13. public class RightTimerTask extends TimerTask {
  14. private int count = 0;
  15.  
  16. public void run() {
  17. try {
  18. System.out.println(count);
  19. count ++;
  20. if (count == 3) {
  21. throw new NullPointerException("Test Exception");
  22. }
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. }
  27.  
  28. public static void main(String[] args) {
  29. try {
  30. RightTimerTask task = new RightTimerTask();
  31. Timer timer = newTimer("TestTimer");
  32. timer.scheduleAtFixedRate(task, 0, 1000);
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }

结果就是:异常也仍然抓住了,定时器也仍然可以继续工作,达到我们本来的目的。

结论:使用 java.util.Timer 时候,在 java.util.TimerTask 的 run() 方法中实现具体操作的时候,必须要抓住所有异常,尤其是 RuntimeException,必须要保证不能往外抛异常,才能保证跟预想的运行情况一致。

 

java定时器的应用举例。JAVA版本定时关机程序

这个程序写的很简单,前段时间一个小MM说:从网上下载很多定时关机器都不好用,让我推荐一个。我下载了一些,觉得是不太好。当时也无聊就应承说我帮你写一个吧,功能很简单。

于是java版的、粗糙的连界面都没有的定时关机器问世了。关机是利用java调用cmd来实现的,其实如果可以采用添加计划任务的方式来实现更好。不废话,上代码

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

MyClock.java

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;

public class MyClock {
public String checkTime() throws ParseException{
   System.out.println("请输入您要关机的时间,格式为mmddhhmm。例:01271010 >>>.............");
   Scanner sca=new Scanner(System.in);
   String time=sca.next();
   DateFormat df=new SimpleDateFormat("yyyyMMddHHmm");
   Date date=df.parse("2010"+time);
   //当输入时间在此刻之前 或者是输入字符数不对的时候再次提醒输入
   while(date.before(new Date())||!time.matches("\\d{8}")){
    date=df.parse("2010"+time);
    System.out.println("时间输入错误,请重新输入正确时间!");
    time=sca.next();
   }
   return "2010"+time;
}
public static void main(String[] args) throws ParseException{
   Timer timer=new Timer();
   Date date=null;
   DateFormat df=new SimpleDateFormat("yyyyMMddHHmmss");
   MyClock m=new MyClock();
   String str=m.checkTime()+"00";
   date=df.parse(str);
   System.out.println("关机时间输入成功,程序已经启动。请勿关闭窗口。");
   timer.schedule(new MyTask(),date);
}
}

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

MyTask.java

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

import java.io.*;
import java.util.TimerTask;

public class MyTask extends TimerTask {

@Override
public void run() {
   try {
      Process pro = Runtime.getRuntime().exec("cmd /c tsshutdn");
      BufferedReader br = new BufferedReader(new InputStreamReader(pro
        .getInputStream()));
      String msg = null;
      while ((msg = br.readLine()) != null) {
       System.out.println(msg);
      }
     } catch (IOException exception) {
     }
   this.cancel();
   System.exit(0);
}

}

 

java定时器

好多朋友用过Windows的任务计划,也有不少程序迷自己曾写过时钟报警、系统自动关机等趣味程序,可却很少有朋友在Web工程中实现过类似功能。
当Web工程启动时,定时器能自动开始计时,在整个Web工程的生命期里,定时器能在每晚深夜触发一次任务。因此定时器的存放位置也值得考查,不能简单的存在于单个Servlet或JavaBean中,必须能让定时器宿主的存活期为整个Web工程生命期,在工程启动时能自动加载运行。结合这两点,跟 Servlet上下文有关的侦听器就最合适不过了,通过在工程的配置文件中加以合理配置,会在工程启动时自动运行,并在整个工程生命期中处于监听状态。

下面就Servlet侦听器结合Java定时器来讲述整个实现过程。要运用Servlet侦听器需要实现 javax.servlet.ServletContextListener接口,同时实现它的contextInitialized (ServletContextEvent event)和contextDestroyed(ServletContextEvent event)两个接口函数。考虑定时器有个建立和销毁的过程,看了前面两个接口函数,就不容置疑的把建立的过程置入 contextInitialized,把销毁的过程置入contextDestroyed了。
我把ServletContextListener的实现类取名为ContextListener,在其内添加一个定时器,示例代码如下所示:
import java.util.Timer;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class ContextListener
extends HttpServlet
implements ServletContextListener {
public ContextListener() {
}

private java.util.Timer timer = null;
public void contextInitialized(ServletContextEvent event) {
timer = new java.util.Timer(true);
event.getServletContext().log("定时器已启动");
timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000);
event.getServletContext().log("已经添加任务调度表");
}

public void contextDestroyed(ServletContextEvent event) {
timer.cancel();
event.getServletContext().log("定时器销毁");
}

}
以上代码中, timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000)这一行为定时器调度语句,其中MyTask是自定义需要被调度的执行任务(在我的财政数据中心项目中就是报表计算引擎入口),从 java.util.TimerTask继承,下面会重点讲述,第三个参数表示每小时(即60*60*1000毫秒)被触发一次,中间参数0表示无延迟。其它代码相当简单,不再详细说明。
下面介绍MyTask的实现,上面的代码中看到了在构造MyTask时,传入了javax.servlet.ServletContext类型参数,是为记录Servlet日志方便而传入,因此需要重载MyTask的构造函数(其父类java.util.TimerTask原构造函数是没有参数的)。在timer.schedule()的调度中,设置了每小时调度一次,因此如果想实现调度任务每24小时被执行一次,还需要判断一下时钟点,以常量C_SCHEDULE_HOUR表示(晚上12点,也即0点)。同时为防止24小时执行下来,任务还未执行完(当然,一般任务是没有这么长的),避免第二次又被调度以引起执行冲突,设置了当前是否正在执行的状态标志isRunning。示例代码如下所示:
import java.util.*;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.*;

public class MyTask extends TimerTask {
private static final int C_SCHEDULE_HOUR = 0;
private static boolean isRunning = false;
private ServletContext context = null;

public MyTask() {
}
public MyTask(ServletContext context) {
    this.context = context;
}

public void run() {
    Calendar cal = Calendar.getInstance();
    if (!isRunning) {
      if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {
        isRunning = true;
        context.log("开始执行指定任务");
        //TODO 添加自定义的详细任务,以下只是示例
        //系统定时接收邮件
        Email email=new Email();
        email.recieve();

        isRunning = false;
        context.log("指定任务执行结束");
      }
    }
    else {
      context.log("上一次任务执行还未结束");
    }
}

}
到这儿,ServletContextListener和MyTask的代码都已完整了。最后一步就是把ServletContextListener部署到您的Web工程中去,在您工程的web.xml配置文件中加入如下三行:

<listener>
<listener-class>com.test.ContextListener</listener-class>
</listener>

当然,上面的com.test得换成您自己的包名了。保存web.xml文件后,把工程打包部署到Tomcat中即可。任务会在每晚12点至凌晨1点之间被执行。

JAVA定时器使用

【1】Java 定时器(java.util.Timer)有定时触发计划任务的功能,通过配置定时器的间隔时间,在某一间隔时间段之后会自动有规律的调用预先所安排的计划任务(java.util.TimerTask)。与每个 Timer 对象相对应的是单个后台线程,用于顺序地执行所有计时器任务。计时器任务应该迅速完成。如果完成某个计时器任务的时间太长,那么它会“独占”计时器的任务执行线程。因此,这就可能延迟后续任务的执行,而这些任务就可能“堆在一起”,并且在上述不友好的任务最终完成时才能够被快速连续地执行。另外,由于我们希望当Web工程启动时,定时器能自动开始计时,在整个Web工程的生命期里,定时器能在每晚深夜触发一次报表计算引擎天等。因此定时器的存放位置也值得考查,不能简单的存在于单个Servlet或JavaBean中,必须能让定时器宿主的存活期为整个Web工程生命期,在工程启动时能自动加载运行。结合这两点,跟Servlet上下文有关的监听器就最合适不过了,通过在工程的配置文件中加以 合理配置,会在工程启动时自动运行,并在整个工程生命期中处于监听状态。   
    下面就Servlet监听器结合Java 定时器来讲述整个实现过程。要运用Servlet监听器需要实现javax.servlet.ServletContextListener接口,同时实现它的contextInitialized(ServletContextEvent event)和contextDestroyed(ServletContextEvent event)两个接口函数。考虑定时器有个建立和销毁的过程,看了前面两个接口函数,就不容置疑的把建立的过程置入 contextInitialized,把销毁的过程置入contextDestroyed了。

package com.korby.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import com.korby.pub.TimerManager;
/**
* 启动定时器的监听器
* @author korby
* @version 1.0
*/

public class TimerListener implements ServletContextListener {
    private TimerManager tm = null;
    public void contextInitialized(ServletContextEvent sce) {
      int day,hour,min,sec;     
       day = 26; hour = 16; min = 42; sec = 0;    
       tm = new TimerManager(day,hour,min,sec);
     }
    public void contextDestroyed(ServletContextEvent sce) {

        tm.destoryTimer();
     }
}

package com.korby.pub;
import java.util.Timer;
import java.util.Date;
import java.util.Calendar;
/**
* 定时器
* @author korby
* @version 1.0
*/
public class TimerManager {
     Timer t = null;
    public TimerManager(int day,int hour,int min,int sec) {
         time(day,hour,min,sec);
     }
    public void time(int day,int hour,int min,int sec){   
     Calendar c = Calendar.getInstance();
     c.set(Calendar.DAY_OF_MONTH,day);
     c.set(Calendar.HOUR_OF_DAY,hour);
     c.set(Calendar.MINUTE,min);
     c.set(Calendar.SECOND,sec);
     Date date = c.getTime();
     System.out.println(c.getTime());
     t= new Timer();
     MyTask mt = new MyTask();
     t.schedule(mt, date);
     }
    public void destoryTimer(){
     t.cancel();
     }
}

package com.korby.pub;

import java.util.TimerTask;

/**

* 计划任务代码

* @author korby

* @version 1.0

*/

public class MyTask extends TimerTask{

    public MyTask() { }

    /**

      * 任务块

     */

    public void run() {

         System.out.println("定时器RUN");

     }

}

在web.xml中设置一个监听器:

<listener>

   <listener-class>com.korby.servlet.TimerListener</listener-class>

</listener>

【2】 java.util.Timer

void cancel()  终止此计时器,丢弃所有当前已安排的任务。

int purge()   从此计时器的任务队列中移除所有已取消的任务。

void schedule(TimerTask task,Date time)  安排在指定的时间执行指定的任务。

void schedule(TimerTask task,Date firstTime, long period)安排指定的任务在指定的时间开始进行重复的固定延迟执行。

void schedule(TimerTask task,long delay)  安排在指定延迟后执行指定的任务。

void schedule(TimerTask task,long delay, long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。

void schedule(TimerTask task,long delay, long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。

void scheduleAtFixedRate(TimerTask task,long delay, long period)安排指定的任务在指定的延迟后开始进行重复的固定速率执行。

【3】java.util.TimerTask由 Timer 安排为一次执行或重复执行的任务。

boolean cancel()          取消此计时器任务。

abstract void run()          此计时器任务要执行的操作。

long scheduledExecutionTime()       返回此任务最近实际 执行的已安排 执行时间。

 

 

Java定时器状态错误:【java.lang.IllegalStateException:Timer already cancelled.】

[10-3-5 13:14:41:729 CST] 1dd900b SystemErr     R java.lang.IllegalStateException: Timer already cancelled.
[10-3-5 13:14:41:731 CST] 1dd900b SystemErr     R at java.util.Timer.sched(Timer.java:312)
[10-3-5 13:14:41:731 CST] 1dd900b SystemErr     R at java.util.Timer.schedule(Timer.java:180)
[10-3-5 13:14:41:731 CST] 1dd900b SystemErr     R at com.yourcompany.businesscomponent.utils.TimerRetrieveDb2Data.main(TimerRetrieveDb2Data.java:37)
[10-3-5 13:14:41:731 CST] 1dd900b SystemErr     R at com.yourcompany.businesscomponent.service.YourBusinessNameFromDb2Service.controlTimerInManual(YourBusinessNameFromDb2Service.java:179)
[10-3-5 13:14:41:731 CST] 1dd900b SystemErr     R at com.yourcompany.businesscomponent.action.YourBusinessNameAction.controlInManual(YourBusinessNameAction.java:617)
[10-3-5 13:14:41:731 CST] 1dd900b SystemErr     R at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[10-3-5 13:14:41:731 CST] 1dd900b SystemErr     R at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
[10-3-5 13:14:41:732 CST] 1dd900b SystemErr     R at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[10-3-5 13:14:41:732 CST] 1dd900b SystemErr     R at java.lang.reflect.Method.invoke(Method.java:324)
[10-3-5 13:14:41:732 CST] 1dd900b SystemErr     R at org.apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.java:280)
[10-3-5 13:14:41:732 CST] 1dd900b SystemErr     R at org.apache.struts.actions.DispatchAction.execute(DispatchAction.java:216)
[10-3-5 13:14:41:732 CST] 1dd900b SystemErr     R at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
[10-3-5 13:14:41:732 CST] 1dd900b SystemErr     R at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
[10-3-5 13:14:41:732 CST] 1dd900b SystemErr     R at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:525)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.servlet.StrictServletInstance.doService(StrictServletInstance.java:110)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.servlet.StrictLifecycleServlet._service(StrictLifecycleServlet.java:174)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.servlet.IdleServletState.service(StrictLifecycleServlet.java:313)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.servlet.StrictLifecycleServlet.service(StrictLifecycleServlet.java:116)
[10-3-5 13:14:41:733 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.servlet.ServletInstance.service(ServletInstance.java:283)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.servlet.ValidServletReferenceState.dispatch(ValidServletReferenceState.java:42)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.servlet.ServletInstanceReference.dispatch(ServletInstanceReference.java:40)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.handleWebAppDispatch(WebAppRequestDispatcher.java:1036)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java:544)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:210)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.srt.WebAppInvoker.doForward(WebAppInvoker.java:139)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.srt.WebAppInvoker.handleInvocationHook(WebAppInvoker.java:332)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.cache.invocation.CachedInvocation.handleInvocation(CachedInvocation.java:71)
[10-3-5 13:14:41:734 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.srp.ServletRequestProcessor.dispatchByURI(ServletRequestProcessor.java:255)
[10-3-5 13:14:41:735 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.oselistener.OSEListenerDispatcher.service(OSEListener.java:334)
[10-3-5 13:14:41:735 CST] 1dd900b SystemErr     R at com.ibm.ws.webcontainer.http.HttpConnection.handleRequest(HttpConnection.java:56)
[10-3-5 13:14:41:736 CST] 1dd900b SystemErr     R at com.ibm.ws.http.HttpConnection.readAndHandleRequest(HttpConnection.java:657)
[10-3-5 13:14:41:736 CST] 1dd900b SystemErr     R at com.ibm.ws.http.HttpConnection.run(HttpConnection.java:463)
[10-3-5 13:14:41:736 CST] 1dd900b SystemErr     R at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:937)
******************************
【问题分析】
如果定时器被执行cancel方法停止之后,再执行schedule()方法的话,会报此异常:【java.lang.IllegalStateException: Timer already cancelled.】
【解决方案】
请检查生成Timer的对象的方式,如果要调用schedule()方法的话,Timer对象需要new一个出来,看Timer的构造器就知道了,
在Timer的构造器中才会调用线程的start()方法。所以:如果你在Timer对象调用cancel()之后,如果要调用schedule()方法,需要
保证Timer的对象是new出来的。

 

 

原创粉丝点击