什么是在Java中安排任务并最小化漂移的最佳方法?

huangapple go评论61阅读模式
英文:

What is the best way to minimize drift while scheduling a task in java?

问题

我正在尝试安排一个任务,但丢失所请求的时间的错误窗口为1-2秒。由于时钟漂移,我想要递归地检查时间并进行调整。我已经在短时间内运行过这段代码(最大延迟:15分钟),而且效果非常好。但在大多数情况下,作业将在从现在开始的8到12小时内安排。

public void scheduleTask(LocalDateTime localDateTime)  {

    long delay = ChronoUnit.MILLIS.between(LocalDateTime.now(), localDateTime);
    if (delay < 30000) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.schedule(() -> myTask(), delay, TimeUnit.MILLISECONDS);
    }
    else {
        try {
            Thread.sleep(delay/2);
        } catch (InterruptedException ignored) {
        }

        scheduleTask(localDateTime);
    }
}

我查看了这里的各种主题,但没有看到真正的解决方案。大多数情况下都说无法按照精确的时间运行代码,因为调度程序是基于延迟而不是给定时间运行的。

调用递归函数会在8-12小时的时间段内对计算机产生任何影响吗?如果是,我应该如何解决这个问题?

英文:

I am trying to schedule a task but the error window for missing the requested time is 1-2 seconds. Because of drift I wanted to check the time recursively and adjust it. I've run this code in short periods of time (max delay: 15 mins) and it worked very well. But the job will be scheduled for 8 to 12 hours from now in most of the cases.

    public void scheduleTask(LocalDateTime localDateTime)  {

        long delay = ChronoUnit.MILLIS.between(LocalDateTime.now(),localDateTime);
        if (delay &lt; 30000) {
            ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
            scheduler.schedule(() -&gt; myTask() ,delay, TimeUnit.MILLISECONDS);
        }
        else {
            try {
                Thread.sleep(delay/2);
            } catch (InterruptedException ignored) {
            }

            scheduleTask(localDateTime);
        }
    }

I looked at various topics here but could not see a real solution. Mostly it is said that it is impossible to run a code in exact time because the schedulers operates based on delay and not on the given time.

Does calling the function recursively affect the computer in any aspect considering 8-12 hours period ? If yes, how should I overcome that ?

答案1

得分: -1

尝试将一个整数值写入文件,该整数值为您希望程序启动事件的UNIX时代值。
经常调用一个函数,将该值与当前的UNIX时代整数进行比较。
如果您需要精确性,请在异步任务中执行。
如果您不需要精确的时间并且不需要在应用程序外触发它,请在诸如创建和恢复之类的其他事件中执行。

如果您需要精确性:
主要问题是保持应用程序处于活动状态。粘性异步任务可以实现这一点。即使使用粘性异步任务,您也可以通过使用Thread.sleep(30000); 使其处于空闲状态(消耗非常少的资源),从而较少地检查文件。

如果有网络连接,您还可以考虑使用Firebase或某些自定义消息系统,在这些系统中,服务器可以通过cron作业传递消息。在稳定的服务器上,cron作业是一种非常可靠的触发远期事件的方式。

英文:

Try writting an int value into a file, with the int of the UNIX epoch you want your program to start an event.
Call frequently a function that checks that value against the current int of UNIX epoch.
If you need precision do it in async task.
If you don't need precise time and don't need it to trigger outside the app, do it in some other event like create and resume.

If you need precision then:
The main problem is to keep the app active. Sticky asynctasks could do that. Even when using sticky async task, you can make it idle (consume very little resources) by using Thread.sleep(30000); and thus checking the file less often.

If internet is present you could also think of firebase or some custom messaging system where server would pass the message with a cron job. Cron jobs on stable servers are a very reliable way of triggering something way in the future.

huangapple
  • 本文由 发表于 2020年9月21日 18:23:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/63990410.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定