保持与后期与后期延迟的时间间隔



我需要运行两个函数,它们之间的时间间隔最小。 出于超出本问题范围的原因,起初我试图控制在 Web 视图中运行的进程(通过 JavascriptInterface)的计时:

webView.post(() -> functionA());
// ... wait 2 secs in javascript and then...
webView.post(() -> functionB());

虽然这在大多数情况下都运行良好,但特别是对于一个用户来说,这两个函数有时似乎紧接着运行(仍然以正确的顺序运行,但没有时间间隔)。

经过反思,这是可以理解的,如果将可运行对象发布到处理程序只会将它们放入队列中,而不能保证根据它们放入队列的时间来维护相对时间。

所以,如果是这样的话,那么我的新策略是忘记从Web视图中运行的javascript中控制时间,而直接在Java中控制它。

所以问题是...按如下方式使用postDelayed()是否保证运行的两个函数之间至少存在最小的时间间隔?

webView.post(() -> functionA());
webView.postDelayed(() -> functionB(), 2000);

我觉得它应该有预期的效果,但我担心它可能与我正在做的事情相同......functionBfunctionA后 2 秒放入队列,不能保证他们实际上会保持他们之间的时间间隔

>post()postDelayed()正在做的是,他们正在向MessageQueue中添加一个MessageLooper循环。因此,post()中的操作不会同步执行,而是会在以后的时间点执行。

webView.post(() -> functionA())将导致添加一个操作,该操作将在将来的某个时间运行,届时webView将传递其measure-layout-draw方法。举个例子,让我们假设这将需要 15 毫秒。

webView.postDelayed(() -> functionB(), 2000)将导致添加一个操作,从现在开始大约在 2 秒内运行。因此,事实上,functionAfunctionB不能保证以 2000 毫秒的间隔调用(而且很可能不会),因为functionA()以"now +15"执行,而functionB()"now + 2000">执行。

相反,如果您有严格的要求,也许您应该使用postAtTime()重载之一,而不是使用postDelayed()

考虑一种方法:执行webView.post(() -> functionA())并在functionA()内部安排一个新的可运行版本,以便在 2000 年代执行,例如Handler().postDelayed(2000, someRunnable)。我认为这可能是您的用例的一种工作方法。

不确定你的意思是问一个Java问题还是一个JavaScript问题。

JavaExecutors框架

如果是Java,解决方案很简单。Java 提供了用于在线程上运行任务的执行器框架。这包括计划任务在初始延迟后运行。(请参阅甲骨文教程。

若要使一对任务之间有时间间隔,请安排第一个任务立即运行。然后,在同一个计划的执行程序服务上,计划第二个任务在延迟后运行。

将任务定义为RunnableCallable对象。

Runnable task = 
() -> { 
System.out.println( "Task is running. " + Instant.now() ); 
}
;

使用Executors实用程序类获取单线程计划执行程序服务。

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;

安排每个任务。

在此示例中,我们立即在后台线程上启动第一个任务。

ses.schedule( task1 , 0 , TimeUnit.SECONDS ) ;  // Runs immediately, in the background on another thread. 

第二个任务将在大约 45 秒后开始,也在后台线程上。

ses.schedule(               // Tell the executor what you want to run, and when you want it run on your behalf in a background thread.
task2 ,                 // Define task to be executed as a `Runnable`.
45 ,                    // Count of time to wait.
TimeUnit.SECONDS        // Specify the granularity of time used in previous argument.
) ; 

捕获异常

提示:请务必使用常规尝试捕获来包装任务中的工作。如果任何未捕获的异常(或错误)一直冒泡到执行程序服务,则服务将停止。将来不会运行任何计划任务。这默默地发生。有关详细信息,请参阅我对相关问题的回答。

关闭线程池

完成所有任务或应用终止时,通过调用计划的执行程序服务之一来关闭其关闭方法之一。否则,支持执行程序服务的线程可能会无限期地继续运行。

雅加达并发实用程序

如果要构建 Web 应用程序,则 JakartaEE 应用程序服务器可能支持Jakarta 并发,以进一步简化此编码并自动关闭执行程序服务的后退线程池。

相关内容

  • 没有找到相关文章

最新更新