2010-03-29 48 views

回答

7

您正在寻找的是一个调度程序。 Quartz可能是Java世界中最常用的调度程序,但如果您已经在使用该框架,Spring会提供一些有趣的调度功能。

无论您选择哪个调度程序,您通常都会指定要发生的操作(有时称为“作业”)和发生的时间(Quartz术语中的“触发器”)。在你的情况下,你会设置触发器每天在午夜运行,当它触发时,它会根据你的工作规定来做你需要做的任何事情。

1

作为一个库,您可以使用Quartz并设置触发器在每晚午夜运行。我认为简单的触发器应该可以完成这项工作。

或者,您可以通过使用单独的线程并休眠直到下一个午夜来实现Quartz自己做些什么。

-1

如果你不想要Quartz或任何其他类似的框架,你可以简单地使用ScheduledExecutorServicescheduleAtFixedRate方法来代替(这里有一个如何在JavaDoc中实例化的例子)。

你唯一需要考虑的是如何计算第一天的开始。

编辑

由于Jarnbjo提到:这将无法生存夏令时间开关,跨越式秒。所以在使用Executor时要注意这一点。

+0

这将无法正常工作,因为午夜不会以固定的速度重新分配。 – jarnbjo 2010-03-29 11:18:09

+0

当然,但在大多数情况下,这并不重要。 – Hardcoded 2010-03-29 11:19:32

+0

如果您想在午夜执行某些操作,那么在11PM或1AM时执行该作业可能不太合适。其中“大多数情况下”是这种可接受的行为? – jarnbjo 2010-03-29 11:39:16

0

这个问题的答案曾经是Quartz。这是Java中调度的事实标准。它很容易使用,但它有点重量级。如果你不关心作业的集群调度或JDBC存储,石英可能会过度杀伤。

谢天谢地,Spring 3.0带有新的调度功能。这些允许简单的“做这个evey 30秒”或者“每天在午夜做这个”类型的调度,而不使用石英。如果您已经在使用弹簧,设置起来非常简单。

例子:

<task:scheduler id="scheduler" pool-size="10"/> 

<task:scheduled-tasks scheduler="scheduler"> 
    <task:scheduled ref="anotherObject" method="anotherMethod" cron="* * 00 * * *"/> 
</task:scheduled-tasks> 

这将导致法 'anotherMethod' 被称为你的bean命名为 'anotherObject' 每天午夜的。更多的信息可以在春季网站上找到:http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/scheduling.html

+1

嗯,调用石英重量级与Spring相比...... – laura 2010-03-29 11:47:26

+0

@laura很多人已经将Spring作为IoC的依赖项。我不建议只将Spring包含在这个功能中,但如果你使用的是弹簧,那么这比重新使用所有的石英轻。 – 2010-03-29 20:12:21

0

你不需要一个庞大的框架。像这样的东西应该工作。

import java.util.*; 
public class Midnight { 
    public static void main(String args[]) { 
     MidnightCowboy mc = new MidnightCowboy(); 
     mc.start(); 
     // on with you normal program flow (if any) here 
    } 
} 

class MidnightCowboy extends Thread { 
    static final boolean COWS_COME_HOME = false; 
    // Whatever data you need should go here 

    public void run() { 
     while (! COWS_COME_HOME) { 
      GregorianCalendar now = new GregorianCalendar(); 
      long nowMilli = now.getTimeInMillis(); 
      now.add(Calendar.DAY_OF_MONTH, 1);  // probably an easier way to set the time to the next midnight 
      now.set(Calendar.HOUR_OF_DAY, 0); 
      now.set(Calendar.MINUTE, 0); 
      now.set(Calendar.SECOND, 0); 
      now.set(Calendar.MILLISECOND, 0); 
      long midnightMilli = now.getTimeInMillis(); 
      long delta = midnightMilli - nowMilli; 
      System.out.println("Waiting " + delta + " milliseconds until midnight."); 
      // How many milliseconds until the next midnight? 
      try { 
       sleep(delta); 
       doSomething(); 
      } catch (InterruptedException e) { 
       System.err.println("I was rudely interrupted!"); 
      } 
     } 
    } 

    void doSomething() { 
     // whatever 
    } 
} 
0

如果你想比整个图书馆更轻量级的解决方案,我发现了一个非常简单的实现here。它基本上是一个Timer类。

当经由Start()方法首先执行类,代码获取的当前时间的日期时间,然后得到午夜的日期时间对象,并以得到的时间,直到它是午夜减去2倍。

此时,它设置定时器间隔并启动定时器。现在,当达到间隔并且定时器触发其事件时,我使用相同的过程重置定时器。这将使间隔为24.当此计时器到期时,它将被重置并无限重复。