Você está na página 1de 5

 

DZone > Java Zone > Em execução no tempo com as tarefas agendadas do Spring

Correndo no tempo com as tarefas


agendadas do Spring
por Dan Newton   NÚCLEO · 06 de fevereiro de 18 · Zona Java ·

Você precisa executar um processo todos os dias na mesma hora, exatamente como um alarme? As tarefas
agendadas do Spring sã o para você . Permitir que você anote um mé todo com @Scheduled faz com que ele
seja executado no horá rio ou intervalo especı́ ico indicado dentro dele. Nesta postagem, veremos a
con iguraçã o de um projeto que pode usar tarefas agendadas e como usar os diferentes mé todos para
de inir quando eles serã o executados.

Eu usarei o Spring Boot para este post, tornando as dependê ncias agradá veis e simples devido ao
agendamento estar disponı́vel para a dependê ncia do spring-boot-starter que será incluı́da em
praticamente todos os projetos do Spring Boot de alguma maneira. Isso permite que você use qualquer
uma das outras dependê ncias do iniciador, pois elas puxam o spring-boot-starter e todos os seus
relacionamentos. Se você deseja incluir a dependê ncia exata em si, use spring-context .

Você pode usar spring-boot-starter .

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.


0.0.RC1</version> </dependency>

Ou use spring-context diretamente.

<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.3.RELEASE


</version> </dependency>

Criar uma tarefa agendada é bastante simples. Adicione a anotaçã o @Scheduled a qualquer mé todo que
você deseja executar automaticamente e inclua @EnableScheduling em um arquivo de con iguraçã o.

Entã o, por exemplo, você pode ter algo como:

@Component public class EventCreator { private static final Logger LOG = LoggerFactory.getLogger(EventCreator.clas
s); private final EventRepository eventRepository; public EventCreator(final EventRepository eventRepository) { thi
s.eventRepository = eventRepository; } @Scheduled(fixedRate = 1000) public void create() { final LocalDateTime star
t = LocalDateTime.now(); eventRepository.save( new Event(new EventKey("An event type", start, UUID.randomUUID()), M
ath.random() * 1000)); LOG.debug("Event created!"); } }

Há bastante có digo aqui que nã o tem importâ ncia para executar uma tarefa agendada. Como eu disse há
um minuto, precisamos usar o @Scheduled em um mé todo, e ele começará a funcionar automaticamente.
Portanto no exemplo acima o mé todo create começará a ser executado a cada 1000ms (1 segundo)
Portanto, no exemplo acima, o metodo create começara a ser executado a cada 1000ms (1 segundo),
conforme indicado pela propriedade fixedRate da anotaçã o. Se quisé ssemos alterar a frequê ncia com
que era executada, poderı́amos aumentar ou diminuir o tempo de fixedRate ou considerar o uso dos
diferentes mé todos de agendamento disponı́veis.

Entã o você provavelmente quer saber quais sã o essas outras formas, certo? Bem, aqui estã o elas (també m
incluirei fixedRate aqui):

fixedRate executa o mé todo com um perı́odo ixo de milissegundos entre invocaçõ es.

fixedRateString é o mesmo que fixedRate mas com um valor de sequê ncia.

fixedDelay executa o mé todo com um perı́odo ixo de milissegundos entre o inal de uma chamada
e o inı́cio da pró xima.
fixedDelayString é o mesmo que fixedDelay mas com um valor de sequê ncia.

cron usa expressõ es do tipo cron para determinar quando executar o mé todo (veremos isso com
mais detalhes posteriormente).

Existem algumas outras propriedades de utilitá rio disponı́veis para a anotaçã o @Scheduled .

zone indica o fuso horá rio para o qual a expressã o cron será resolvida. Se nenhum fuso horá rio
estiver incluı́do, ele usará o fuso horá rio padrã o do servidor. Portanto, se você precisar executar um
fuso horá rio especı́ ico, por exemplo, Hong Kong, poderá usar zone = "GMT+8:00" .
initialDelay é o nú mero de milissegundos para atrasar a primeira execuçã o de uma tarefa
agendada. Ele requer que uma das propriedades de taxa ixa ou atraso ixo seja usada.
initialDelayString é o mesmo que initialDelay mas com um valor de sequê ncia.

Alguns exemplos de uso de taxas e atrasos ixos podem ser encontrados abaixo:

O mesmo que antes - é executado a cada 1 segundo:

@Scheduled(fixedRate = 1000)

O mesmo que acima:

@Scheduled(fixedRateString = "1000")

Executa 1 segundo apó s a conclusã o da chamada anterior:

@Scheduled(fixedDelay = 1000)

Executa a cada segundo, mas aguarda 5 segundos antes de ser executado pela primeira vez:

@Scheduled(fixedRate = 1000, initialDelay = 5000)

Agora, olhando para a propriedade cron , que oferece muito mais controle sobre o agendamento de uma
tarefa. Permite de inir os segundos, minutos e horas em que a tarefa é executada, mas pode ir ainda mais
longe e especi icar até os anos em que uma tarefa será executada.

Abaixo está uma aná lise dos componentes que constroem uma expressã o cron.

Seconds podem ter valores de 0-59 a 0-59 ou os caracteres especiais , - * / .

Minutes podem ter valores de 0-59 a 0-59 ou os caracteres especiais , - * / .

Hours podem ter valores de 0-59 a 0-59 ou os caracteres especiais , - * / .

Day of month pode ter valores de 1 a 1-31 ou os caracteres especiais , - * ? / LWC


, - * ? / LWC .

Month pode ter valores de 1-12 , JAN-DEC ou os caracteres especiais , - * / .

Day of week pode ter valores de 1-7 , SUN-SAT ou os caracteres especiais , - * ? / LC #


, - * ? / LC # .

Year pode estar vazio, ter valores 1970-2099 ou os caracteres especiais , - * / .

Apenas para maior clareza, combinei a divisã o em uma expressã o que consiste nos ró tulos dos campos.

@Scheduled(cron = "[Seconds] [Minutes] [Hours] [Day of month] [Month] [Day of week] [Year]")

Por favor, nã o inclua o aparelho nas suas expressõ es (usei-as para tornar a expressã o mais clara).

Antes de seguirmos em frente, precisamos analisar o signi icado dos caracteres especiais.

* representa todos os valores. Portanto, se for usado no segundo campo, signi ica cada segundo. Se
for usado no campo dia, signi ica executar todos os dias.
? representa nenhum valor especı́ ico e pode ser usado no campo dia do mê s ou dia da semana -
onde o uso de um invalida o outro. Se o especi icarmos para disparar no 15º dia do mê s, entã o a ?
será usado no campo Day of week .
- representa um intervalo inclusivo de valores. Por exemplo, 1-3 no campo horas signi ica as horas
1, 2 e 3.
, representa valores adicionais. Por exemplo, colocar MON, WED, SUN no campo dia da semana
signi ica segunda, quarta e domingo.
/ representa incrementos. Por exemplo, 0/15 no campo de segundos é acionado a cada 15
segundos, começando em 0 (0, 15, 3,0 e 45).
L representa o ú ltimo dia da semana ou mê s. Lembre-se de que sá bado é o im da semana neste
contexto, portanto, usar L no campo dia da semana será acionado no sá bado. Isso pode ser usado
em conjunto com um nú mero no campo dia do mê s, como 6L para representar a ú ltima sexta-feira
do mê s ou uma expressã o como L-3 indica o terceiro do ú ltimo dia do mê s. Se especi icarmos um
valor no campo dia da semana, devemos usar ? no campo dia do mê s e vice-versa.
W representa o dia da semana mais pró ximo do mê s. Por exemplo, 15W serã o acionados no 15º dia
do mê s, se for um dia da semana. Caso contrá rio, ele será executado no dia da semana mais pró ximo.
Este valor nã o pode ser usado em uma lista de valores do dia.
# especi ica o dia da semana e a semana que a tarefa deve disparar. Por exemplo, 5#2 signi ica a
segunda quinta-feira do mê s. Se o dia e a semana que você especi icou estourarem no pró ximo mê s,
ele nã o será acionado.

Um recurso ú til com explicaçõ es um pouco mais longas pode ser encontrado aqui , o que me ajudou a
escrever este post.

Vamos ver alguns exemplos:

Incê ndios à s 12h todos os dias:

@Scheduled(cron = "0 0 12 * * ?")

Incê ndios à s 10h15 todos os dias no ano de 2005:

@Scheduled(cron = "0 15 10 * * ? 2005")

Dispara a cada 20 segundos:

@Scheduled(cron = "0/20 * * * * ?")

Para mais alguns exemplos, consulte o link que mencionei anteriormente, mostrado novamente aqui .
Felizmente, se você icar paralisado ao escrever uma expressã o cron simples, poderá procurar no Google o
cená rio que precisa - já que algué m provavelmente já fez a mesma pergunta no Stack Over low.

Para amarrar algumas das liçõ es acima em um pequeno exemplo de có digo, consulte o có digo abaixo:

@Component public class AverageMonitor { private static final Logger LOG = LoggerFactory.getLogger(AverageMonitor.
class); private final EventRepository eventRepository; private final AverageRepository averageRepository; public Av
erageMonitor( final EventRepository eventRepository, final AverageRepository averageRepository) { this.eventReposit
ory = eventRepository; this.averageRepository = averageRepository; } @Scheduled(cron = "0/20 * * * * ?") public voi
d publish() { final double average = eventRepository.getAverageValueGreaterThanStartTime( "An event type", LocalDat
eTime.now().minusSeconds(20)); averageRepository.save( new Average(new AverageKey("An event type", LocalDateTime.no
w()), average)); LOG.info("Average value is {}", average); } }

Aqui, temos uma classe que está consultando Cassandra a cada 20 segundos para obter o valor mé dio dos
eventos no mesmo perı́odo. Novamente, a maior parte do có digo aqui é ruı́do da anotaçã o @Scheduled ,
mas pode ser ú til vê -lo em estado selvagem. Alé m disso, se você estiver atento, neste caso de uso de
execuçã o a cada 20 segundos, usar as propriedades fixedRate e possivelmente fixedDelay vez de
cron seria adequado aqui, pois estamos executando a tarefa com tanta frequê ncia:

@Scheduled(fixedRate = 20000)

E o fixedRate equivalente da expressã o cron usada acima.

O requisito inal, que eu aludi anteriormente, é adicionar a anotaçã o @EnableScheduling a uma classe de
con iguraçã o:

@SpringBootApplication @EnableScheduling public class Application { public static void main(final String args[]) {
SpringApplication run(Application class); } }
SpringApplication.run(Application.class); } }

Sendo este um pequeno aplicativo Spring Boot, anexei a anotaçã o @EnableScheduling à classe principal
@SpringBootApplication .

Em conclusã o, podemos agendar tarefas para serem acionadas usando a anotaçã o @Scheduled
juntamente com uma taxa de milissegundos entre execuçõ es ou uma expressã o cron para tempos mais
precisos que nã o podem ser expressos com a primeira. Para tarefas que precisam ser executadas com
muita frequê ncia, o uso das propriedades fixedDelay ou fixedDelay será su iciente, mas, quando o
tempo entre as execuçõ es aumentar, será mais difı́cil determinar rapidamente o tempo de inido. Quando
isso ocorre, a propriedade cron deve ser usada para melhor clareza do tempo agendado.

A pequena quantidade de có digo usada neste post pode ser encontrada no meu GitHub .

Se você achou este post ú til e deseja manter-se atualizado com meus novos tutoriais enquanto os escrevo,
siga-me no Twitter em @LankyDanDev .

Como este artigo? Leia mais do DZone


Implementando um bloqueio do Como agendar uma tarefa com um
Texto original em Inglês:
agendador atraso fixo na inicialização do Spring
If you found this post helpful and wish to keep up to date with my new tutorials as I write them, follow me on Twitter at
[Video]
@LankyDanDev .

Sugira uma
Como agendar uma tradução
tarefamelhor
usando a Cartão DZone grátis
expressão Cron na inicialização por Introdução ao CMS sem cabeça
primavera [Vídeo]

BAIXAR

Tópicos: JAVA, TAREFAS AGENDADAS, PRIMAVERA, BOOT DE PRIMAVERA, TUTORIAL

Publicado na DZone com permissão de Dan Newton , DZone MVB . Veja o artigo original aqui. 
As opiniões expressas pelos colaboradores da DZone são suas.

Você também pode gostar