java定时任务

全文检索系统需要定时建立索引,故需要定时执行某些任务,以下是实现思路:

单次任务使用timer.schedule(new task(),Date date)实现。

每天任务与每周任务使用timer.scheduleAtFixedRate(new task(),delay,period)实现,周期分别为24*1000/7*24*1000。

每月任务同每天任务,但周期不确定,思虑良久,采用java反射机制动态修改周期。

代码如下:

1、创建ServletContextListener类

package org.fulltext.task;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
/**
 * Application Lifecycle Listener implementation class TaskListener
 *
 */
@WebListener
public class TaskListener implements ServletContextListener {
    /**
     * Default constructor. 
     */
    public TaskListener() {
        // TODO Auto-generated constructor stub
    }
 /**
     * @see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    public void contextDestroyed(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
     TaskManager.destoryTimer();
     
     
    }
 /**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    public void contextInitialized(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
     TaskManager taskManager=new TaskManager();
    }
 
}

2、修改web.xml文件,在web-app下添加时间侦听。

  <listener>

   <listener-class>

     org.fulltext.task.TaskListener

   </listener-class>

  </listener>

3、创建taskManager类,该类通过timer执行定时任务,是定时任务的核心。

package org.fulltext.task;
public class TaskManager {
 
 static Logger logger=Logger.getLogger("logfile");
 public static List<Timer> timers=new ArrayList<Timer>();
 public TaskManager(){ 
  List<Taskconfig> taskconfigs=new ArrayList<Taskconfig>();
  TaskconfigDAO taskconfigDAO=new TaskconfigDAO();
  taskconfigs=taskconfigDAO.findAll();
  SimpleDateFormat simpleDateFormat;
  for (int i = 0; i <taskconfigs.size(); i++) {
   timers.add(i,new Timer("Tasktimer"+i,true));
  }
  for (int i = 0; i < taskconfigs.size(); i++) {
   if(taskconfigs.get(i).getTaskstate().trim().equals("0")||taskconfigs.get(i).getTaskstate().trim().equals("3")){
   }
   else{
    switch (taskconfigs.get(i).getTaskperiod().trim()) {
    case "once":
     
     if (taskconfigs.get(i).getTaskexcetime().before(new Date())) {
      simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
      logger.warn("单次任务调度失败,原因:执行时间小于当前时间,"+"任务名:"+taskconfigs.get(i).getTaskname()+",任务所属"+taskconfigs.get(i).getTasktype()+",任务操作:"
        +taskconfigs.get(i).getTaskoperate()+" ,任务周期:"+taskconfigs.get(i).getTaskperiod()+",任务执行时间:"+simpleDateFormat.format(taskconfigs.get(i).getTaskexcetime()).toString());
      taskconfigs.get(i).setTaskstate("3");
      taskconfigDAO.save(taskconfigs.get(i));
     }
     else{
      simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
      logger.info("单次任务调度成功,任务名:"+taskconfigs.get(i).getTaskname()+",任务所属"+taskconfigs.get(i).getTasktype()+",任务操作:"
        +taskconfigs.get(i).getTaskoperate()+" ,任务周期:"+taskconfigs.get(i).getTaskperiod()+",任务执行时间:"+simpleDateFormat.format(taskconfigs.get(i).getTaskexcetime()).toString());
      if ("recreate_index".equals(taskconfigs.get(i).getTaskoperate().trim())) {
       timers.get(i).schedule(new RecreateIndexTask(taskconfigs.get(i)), taskconfigs.get(i).getTaskexcetime());
      }else {
       timers.get(i).schedule(new CrawlIndexTask(taskconfigs.get(i)), taskconfigs.get(i).getTaskexcetime());
      }
     }
     break;
    case "day":
     long PERIOD_DAY = 24*60*60*1000;
     Calendar now=Calendar.getInstance();
     Calendar excetimeCalendar=Calendar.getInstance();
     excetimeCalendar.setTime(taskconfigs.get(i).getTaskexcetime());
     now.set(Calendar.HOUR_OF_DAY, excetimeCalendar.get(Calendar.HOUR_OF_DAY));
     now.set(Calendar.MINUTE, excetimeCalendar.get(Calendar.MINUTE));
     now.set(Calendar.SECOND, excetimeCalendar.get(Calendar.SECOND));
     Date excDate=now.getTime();
     while(excDate.before(new Date())){
      now.add(Calendar.DAY_OF_MONTH, 1);
      excDate=now.getTime();
     }
     simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
     logger.info("每天任务调度成功,任务名:"+taskconfigs.get(i).getTaskname()+",任务所属"+taskconfigs.get(i).getTasktype()+",任务操作:"
       +taskconfigs.get(i).getTaskoperate()+" ,任务周期:"+taskconfigs.get(i).getTaskperiod()+",任务执行时间:"+simpleDateFormat.format(taskconfigs.get(i).getTaskexcetime()).toString());
     if ("recreate_index".equals(taskconfigs.get(i).getTaskoperate().trim())) {
      timers.get(i).scheduleAtFixedRate(new RecreateIndexTask(taskconfigs.get(i)), excDate,PERIOD_DAY);
      }else {
      timers.get(i).scheduleAtFixedRate(new CrawlIndexTask(taskconfigs.get(i)),excDate,PERIOD_DAY);
      }
     break;
    case "week":
     long PERIOD_WEEK = 7*24*60*60*1000;
     Calendar week_now=Calendar.getInstance();
     Calendar excetimeweek=Calendar.getInstance();
     excetimeweek.setTime(taskconfigs.get(i).getTaskexcetime());
     week_now.set(Calendar.DAY_OF_WEEK, new Integer(taskconfigs.get(i).getTaskweekday().trim()));
     week_now.set(Calendar.HOUR_OF_DAY, excetimeweek.get(Calendar.HOUR_OF_DAY));
     week_now.set(Calendar.MINUTE, excetimeweek.get(Calendar.MINUTE));
     week_now.set(Calendar.SECOND, excetimeweek.get(Calendar.SECOND));
     Date wexcDate=week_now.getTime();
     System.out.println(wexcDate+"===="+new Date());
     while(wexcDate.before(new Date())){
      week_now.add(Calendar.DAY_OF_MONTH, 7);
      wexcDate=week_now.getTime();
     }
     simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
     logger.info("每周任务调度成功,任务名:"+taskconfigs.get(i).getTaskname()+",任务所属"+taskconfigs.get(i).getTasktype()+",任务操作:"
       +taskconfigs.get(i).getTaskoperate()+" ,任务周期:"+taskconfigs.get(i).getTaskperiod()+",任务执行时间:"+simpleDateFormat.format(taskconfigs.get(i).getTaskexcetime()).toString());
     if ("recreate_index".equals(taskconfigs.get(i).getTaskoperate().trim())) {
      System.out.println(wexcDate);
      timers.get(i).scheduleAtFixedRate(new RecreateIndexTask(taskconfigs.get(i)), wexcDate,PERIOD_WEEK);
      }else {
      timers.get(i).scheduleAtFixedRate(new CrawlIndexTask(taskconfigs.get(i)),wexcDate,PERIOD_WEEK);
      }
 
     break;
    case "month":
     Calendar month_now=Calendar.getInstance();
     Calendar excetime_month=Calendar.getInstance();
     excetime_month.setTime(taskconfigs.get(i).getTaskexcetime());
     while (month_now.getActualMaximum(Calendar.DAY_OF_MONTH)<new Integer(taskconfigs.get(i).getTaskmonday().trim())) {
      logger.warn("调度每月任务,因当前月份:"+(month_now.get(Calendar.MONTH)+1)+"月没有"+taskconfigs.get(i).getTaskmonday().trim()+"号,最大天数为:"+month_now.getActualMaximum(Calendar.DAY_OF_MONTH)+"故延后一月");
      month_now.add(Calendar.MONTH, 1);
     }
     month_now.set(Calendar.DAY_OF_MONTH, new Integer(taskconfigs.get(i).getTaskmonday().trim()));
     month_now.set(Calendar.HOUR_OF_DAY, excetime_month.get(Calendar.HOUR_OF_DAY));
     month_now.set(Calendar.MINUTE, excetime_month.get(Calendar.MINUTE));
     month_now.set(Calendar.SECOND, excetime_month.get(Calendar.SECOND));
     Date monthDate=month_now.getTime();
     while(monthDate.before(new Date())){
      month_now.add(Calendar.MONTH, 1);
      monthDate=month_now.getTime();
     }
     long PERIOD_month = month_now.getActualMaximum(Calendar.DAY_OF_MONTH)*24*60*60*1000L;
     simpleDateFormat=new SimpleDateFormat("HH:mm:ss");
     logger.info("每月任务调度成功,任务名:"+taskconfigs.get(i).getTaskname()+",任务所属"+taskconfigs.get(i).getTasktype()+",任务操作:"
       +taskconfigs.get(i).getTaskoperate()+" ,任务周期:"+taskconfigs.get(i).getTaskperiod()+",任务执行时间:"+simpleDateFormat.format(taskconfigs.get(i).getTaskexcetime()).toString());
     if ("recreate_index".equals(taskconfigs.get(i).getTaskoperate().trim())) {
       timers.get(i).scheduleAtFixedRate(new ReIndexOfMonth(taskconfigs.get(i)), monthDate,PERIOD_month);
      
      }else {
       timers.get(i).scheduleAtFixedRate(new CrawlIndexOfMonth(taskconfigs.get(i)), monthDate,PERIOD_month);
      }
     break;
    default:
     break;
    }
   }
  }
  HibernateSessionFactory.closeSession();
 }
 
 public static void destoryTimer() {
  for(int i=0;i<timers.size();i++){
   timers.get(i).cancel();
   timers.get(i).purge();
  }
  Map<Thread,StackTraceElement[]> threadmMap=Thread.getAllStackTraces();
     Set<Thread> keyThreads=threadmMap.keySet();      
     for (Iterator<Thread> it = keyThreads.iterator(); it.hasNext();) {           
      Thread thread=it.next();   
       if(thread.getName().indexOf("Tasktimer")>=0)
       thread.interrupt();
      }
  timers.clear();
  System.gc();
 }
}

4、最后创建timerTask类,该类包含run方法,run方法中放置需要执行的任务代码。

package org.fulltext.task;

import java.lang.reflect.Field;

import java.util.TimerTask;

import org.apache.commons.collections.map.StaticBucketMap;

public class ExecuteTask extends TimerTask{
 public void run() {
  // TODO Auto-generated method stub
  System.out.println("运行计划任务");
  setDeclaredField(TimerTask.class, this, "period", 1000);
 }
}

5、每月任务周期不固定,使用java反射机制动态修改执行周期字段。

package org.fulltext.task;
import java.lang.reflect.Field;
import java.util.TimerTask;
import org.apache.commons.collections.map.StaticBucketMap;
public class ExecuteTask extends TimerTask{
 static int p=0;
    static boolean setDeclaredField(Class<?> clazz, Object obj,  
        String name, int value) {  
     p=p+value;
        try {  
            Field field = clazz.getDeclaredField(name);  
            field.setAccessible(true);  
            field.set(obj, p);  
            return true;  
        } catch (Exception ex) {  
            ex.printStackTrace();  
            return false;  
        }  
    }
 @Override
 public void run() {
  // TODO Auto-generated method stub
  System.out.println("测试java反射机制");
  setDeclaredField(TimerTask.class, this, "period", 1000);
 }
}

编写timer时,需要释放资源,否则系统重启或重新加载任务会继续调度执行。 在ServletContextListener的contextDestroyed方法中添加删除timer取消及删除功能。

你可能感兴趣的:(java定时任务)