我需要运行两个函数,它们之间的时间间隔最小。 出于超出本问题范围的原因,起初我试图控制在 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);
我觉得它应该有预期的效果,但我担心它可能与我正在做的事情相同......functionB
在functionA
后 2 秒放入队列,不能保证他们实际上会保持他们之间的时间间隔
>post()
和postDelayed()
正在做的是,他们正在向MessageQueue
中添加一个Message
,Looper
循环。因此,post()
中的操作不会同步执行,而是会在以后的时间点执行。
webView.post(() -> functionA())
将导致添加一个操作,该操作将在将来的某个时间运行,届时webView
将传递其measure-layout-draw
方法。举个例子,让我们假设这将需要 15 毫秒。
webView.postDelayed(() -> functionB(), 2000)
将导致添加一个操作,从现在开始大约在 2 秒内运行。因此,事实上,functionA
和functionB
不能保证以 2000 毫秒的间隔调用(而且很可能不会),因为functionA()
以"now +15"执行,而functionB()
以"now + 2000">执行。
相反,如果您有严格的要求,也许您应该使用postAtTime()
重载之一,而不是使用postDelayed()
?
考虑一种方法:执行webView.post(() -> functionA())
并在functionA()
内部安排一个新的可运行版本,以便在 2000 年代执行,例如Handler().postDelayed(2000, someRunnable)
。我认为这可能是您的用例的一种工作方法。
不确定你的意思是问一个Java问题还是一个JavaScript问题。
JavaExecutors框架
如果是Java,解决方案很简单。Java 提供了用于在线程上运行任务的执行器框架。这包括计划任务在初始延迟后运行。(请参阅甲骨文教程。
若要使一对任务之间有时间间隔,请安排第一个任务立即运行。然后,在同一个计划的执行程序服务上,计划第二个任务在延迟后运行。
例
将任务定义为Runnable
或Callable
对象。
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 并发,以进一步简化此编码并自动关闭执行程序服务的后退线程池。