Pergunta

Meu programa tem um componente - apelidado de Scheduler - que permite que outros componentes registar pontos no tempo em que eles querem ser chamado de volta. Isso deve funcionar muito parecido com o serviço cron Unix, i. e. você diz ao Scheduler "notificar-me em dez minutos depois de cada hora cheia".

Eu percebo não há retornos reais em Java.

Aqui está a minha abordagem, há uma biblioteca que já faz isso? Sinta-se livre para sugerir melhorias também.

Register chamada para Scheduler passa:

  • a especificação de tempo contendo hora, minuto, segundo, mês do ano, dom, dow, onde cada item pode ser indeterminado, que significa "executá-lo a cada hora / minuto etc." (Assim como crontabs)
  • um objeto que contenha dados que irá dizer o objeto de chamada o que fazer quando é notificado pelo Scheduler. Será que o Scheduler não processar esses dados, apenas armazena e passa-lo de volta após a notificação.
  • uma referência para o objeto de chamada

Na inicialização, ou após um novo pedido de registro, o Scheduler inicia com um objeto Calendário da hora atual do sistema e verifica se existem entradas no banco de dados que correspondem neste momento. Se houver, eles são executados e o processo começa de novo. Se não houver, o tempo no objeto Calendar é incrementado por um segundo e os entreis são verificados novamente. Isso se repete até que haja uma entrada ou mais que jogo (es). (Discrete Simulation Event)

O Scheduler, então, lembre-se que timestamp, dormir e acordar a cada segundo para verificar se ele já está lá. Se acontecer de acordar e o tempo já passou, ele começa de novo, da mesma forma, se o tempo veio e os trabalhos foram executados.


Editar : Obrigado por me apontando para Quartz. Eu estou procurando algo muito menor, no entanto.

Foi útil?

Solução

Se suas necessidades são simples, considere o uso java .util.Timer :

public class TimerDemo {

  public static void main(String[] args) {
    // non-daemon threads prevent termination of VM
    final boolean isDaemon = false;
    Timer timer = new Timer(isDaemon);

    final long threeSeconds = 3 * 1000;
    final long delay = 0;
    timer.schedule(new HelloTask(), delay, threeSeconds);

    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.MINUTE, 1);
    Date oneMinuteFromNow = calendar.getTime();

    timer.schedule(new KillTask(timer), oneMinuteFromNow);
  }

  static class HelloTask extends TimerTask {
    @Override
    public void run() {
      System.out.println("Hello");
    }
  }

  static class KillTask extends TimerTask {

    private final Timer timer;

    public KillTask(Timer timer) {
      this.timer = timer;
    }

    @Override
    public void run() {
      System.out.println("Cancelling timer");
      timer.cancel();
    }
  }

}

Como tem sido observou , o ExecutorService de < a href = "http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-frame.html" rel = "nofollow noreferrer"> java.util.concurrent ofertas uma API mais rico se você precisar dele.

Outras dicas

Se seus objetos sabe exatamente os pontos individuais em vez que desejam ser executado, em seguida, você poderia usar um java.util.concurrent.ScheduledExecutorService. Em seguida, eles simples chamada:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
long timeToExecute = ... //read from DB? use CronTrigger?
long delayToExecution = timeToExecute - System.currentTimeMillis();
scheduler.schedule(aRunnable, delayToExecution, TimeUnit.MILLISECONDS);

Você só precisa usar Quartz se você quiser o próprio programador para lidar com funcionalidades como "executar cada 5 segundos", ou se você quiser um comportamento complexo em torno de execuções, ou a persistência da trilha de auditoria de execução perdeu.

classe CronTrigger

Você pode realmente trivialmente reutilização de quartzo para obter um "próximo tempo de execução". A classe é completamente autônomo e não depende de ser chamado de dentro do Quartz "contexto". Depois de ter o seguinte tempo de execução como um Date ou long, você pode simplesmente usar o ScheduledExecutorService Java como acima

Quartz é a força motriz grande e óbvio nesta área, mas existem algumas alternativas para explorar .

Cron4j é uma biblioteca bastante decente, que é um pouco mais leve do que o quartzo. Ele fornece uma boa documentação e vai fazer o que quiser.

Provavelmente mais interessante é que se você quiser usar uma biblioteca que se encaixa melhor com bibliotecas de simultaneidade de Java (particularmente executores e ScheduledExecutors), em seguida, HA-JDBC tem um CronExecutorService interface, executado pelo CronThreadPoolExecutor . Agora, curiosamente, tem uma dependência em quartzo (para fornecer a classe CronExpression), mas eu acho que o trabalho dois juntos melhor do que apenas Quartz sozinho. Se você não quer grandes dependências, é fácil de extrair o punhado de aulas de quartzo e HA-JDBC que fazem isso acontecer.

Uma vez que você quer algo muito menor (só notei a sua edição), grab CronExpression de quartzo, e as duas classes HA-JDBC eu mencionei acima. Isso vai fazê-lo.

Eu recomendaria fortemente cron4j (já mencionado) ao longo de quartzo, a menos que você absolutamente necessidade alguns dos recursos mais avançados e complexos de quartzo. Cron4j foca muito bem sobre o que é suposto fazer, tem documentação decente, e não é uma solução cozinha-pia.

Quartz programador é geralmente recomendado.

Não posso acreditar java.util.Timer foi votado como a resposta. Quartz é realmente uma escolha melhor muito.

A grande vantagem de quartzo sobre java.util.Timer é que com quartzo os trabalhos podem ser armazenados no db. Como um resultado uma JVM pode programar e outro pode executar. Também (obviamente) os sobrevive solicitação através JVM reiniciado.

Provavelmente mais interessante é que se você quiser usar uma biblioteca que se encaixa melhor com bibliotecas de simultaneidade de Java (particularmente executores e ScheduledExecutors), em seguida, HA-JDBC tem uma interface CronExecutorService, executado pelo CronThreadPoolExecutor. Agora, curiosamente, tem uma dependência em quartzo (para fornecer a classe CronExpression), mas eu acho que o trabalho dois juntos melhor do que apenas Quartz sozinho. Se você não quer grandes dependências, é fácil de extrair o punhado de aulas de quartzo e HA-JDBC que fazem isso acontecer.

Eu só queria dizer que eu tentei extrair essas classes, e funcionou! Eu precisava dessas três classes:

  • CronExpression (quartzo)
  • CronThreadPoolExecutor (ha-jdbc)
  • DaemonThreadFactory (ha-jdbc)

E eu só tinha que fazer esses pequenos ajustes:

  • Retirar o logger de CronThreadPoolExecutor (ele foi criado, mas nunca utilizado)
  • Movido a YEAR_TO_GIVEUP_SCHEDULING_AT constante de CronTrigger para CronExpression

Eu estava emocionado que eu não consegui puxar preso em um emaranhado de dependências. Parabéns aos autores classe!

E tem trabalhado como um campeão.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top