22

我正在使用@ScheduledSpring 框架中的注释来调用方法。但是我的设置中有多个节点,我不希望它们同时运行。所以我想为初始延迟设置一个随机值,以使它们相互抵消。

import org.springframework.scheduling.annotation.Scheduled;

@Scheduled(fixedRate = 600000, initialDelay = <random number between 0 and 10 minutes> )

不幸的是,我在这里只允许使用常量表达式。有没有其他方法可以解决这个问题?我想到了使用 Spring 表达式语言。

4

7 回答 7

19

您可以通过 Spring 表达式语言配置 initialDelay:

@Scheduled(fixedRate = 600000, initialDelayString = "#{ T(java.util.concurrent.ThreadLocalRandom).current().nextInt(10*60*1000) }" )

我现在没有 IDE 来测试该代码,因此您可能需要稍微调整一下。

于 2015-01-10T01:18:26.320 回答
18

要使初始延迟随机介于 0 之间,请fixedRate尝试以下操作:

@Scheduled(fixedDelayString = "${some.delay}", initialDelayString = "${random.int(${some.delay})}")

您将some.delay(但选择更合适的名称)定义为 10 分钟作为您的 application.properties 或等效项中的属性。

some.delay = 600000

当然,如果您想懒惰和硬编码,您可以随时使用${random.int(600000)}

于 2016-07-12T02:01:15.193 回答
4

在这个工作示例中,随机延迟将在 5 到 10 秒之间。

@Scheduled(fixedDelayString = "#{new Double((T(java.lang.Math).random() + 1) * 5000).intValue()}")
于 2017-01-23T21:26:57.920 回答
2

请记住,initialDelayString 仅在启动时评估一次,然后在调度作业时使用相同的值。

见 org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor#processScheduled

于 2016-07-25T07:02:21.853 回答
1

这应该工作

@Scheduled(fixedRate = 600000, initialDelay = "#{new java.util.Random().nextInt(700)}")

用这个简单的测试验证它:

    @Test
    public void testSpEL() {
       ExpressionParser parser = new SpelExpressionParser();
       Expression exp = parser.parseExpression("new java.util.Random().nextInt(500)");
       Integer value =(Integer) exp.getValue();
       Assertions.assertThat(value).isNotNull();
}
于 2020-11-06T16:28:38.637 回答
0

在科特林这有效:

@Component
class MyJob {
   companion object {
      const val INTERVAL = 24*3600*1000L // once a day
   }

   @Scheduled(fixedRate = INTERVAL, initialDelayString = "\${random.long($INTERVAL)}")
   fun doDaily() {
      ...
   }
}
于 2019-08-28T11:40:43.270 回答
-5

或者您可以在函数末尾添加 Thread.sleep(...) 。

@Scheduled(fixedDelay = 10000)
public void replicateData() {

    ... do stuff ...

    try {
        Thread.sleep(RandomUtils.nextLong(1000, 10000));
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
于 2017-05-19T09:59:26.753 回答