TimerTask、Thread.sleep和Handler postDelayed - 哪个最准确地每N毫秒调用函数?

67
什么是每隔N毫秒调用函数的最准确的方法?
  • 使用Thread.sleep的线程
  • TimerTask
  • 使用postDelayed的Handler
我使用Thread.sleep修改了这个示例,但不够准确。
我正在开发一个音乐应用程序,它将以给定的BPM播放声音。我知道创建完全准确的节拍器是不可能的,我也不需要 - 只是想找到最好的方法来实现这一点。
谢谢

我更喜欢使用计时器来实现这个。 - Biraj Zalavadia
@BirajZalavadia 不要使用Timer(http://www.mopri.de/2010/timertask-bad-do-it-the-android-way-use-a-handler/),而是使用Handler或ScheduledThreadPoolExecutor。 - AppiDevo
4个回答

76

使用Timer存在一些缺点:

  • 它只创建单个线程来执行任务,如果一个任务运行时间太长,则其他任务会受到影响。
  • 它不能处理任务抛出的异常,线程就会终止,这会影响其他计划中的任务,它们将无法运行。

ScheduledThreadPoolExecutor可以正确地处理所有这些问题,因此使用Timer没有意义。在您的情况下,有两种方法可能会有用:scheduleAtFixedRate(...)和scheduleWithFixedDelay(..)。

class MyTask implements Runnable {

  @Override
  public void run() {
    System.out.println("Hello world");
  } 
}

ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
long period = 100; // the period between successive executions
exec.scheduleAtFixedRate(new MyTask(), 0, period, TimeUnit.MICROSECONDS);
long delay = 100; //the delay between the termination of one execution and the commencement of the next
exec.scheduleWithFixedDelay(new MyTask(), 0, delay, TimeUnit.MICROSECONDS);

哇!非常感谢 - 这几乎是完美无瑕的!比我以前的方法时间明显更好。 - fxfuture
我正在尝试使用这种方法来执行定期任务,但似乎并不起作用。https://dev59.com/X4bca4cB1Zd3GeqPaMYE - dowjones123

7
在Android上,您可以创建具有自己的Handler/Message Queue的线程。它非常准确。当您查看Handler documentation时,可以看到它是为此而设计的。
引用: 有两个主要用途:(1)调度消息和可运行项以在将来某个时间执行;(2)将操作排队以在不同于您自己的线程上执行。

1

从精度上看,它们都是相同的。Java的时间精度取决于系统定时器和调度程序的精度和准确性,并不保证。请参见Thread.sleep和Object.wait API。


-13
使用 TimerTask 来进行循环操作是更好的选择。建议使用。

2
我非常怀疑,看看这个链接:http://androidtrainningcenter.blogspot.in/2013/12/handler-vs-timer-fixed-period-execution.html - headsvk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接