【问题标题】:java.lang.IllegalStateException: TimerTask is scheduled already: Rationally using of Timer and TimerTask in Androidjava.lang.IllegalStateException: TimerTask 已被调度:Android 中 Timer 和 TimerTask 的合理使用
【发布时间】:2014-05-14 07:31:47
【问题描述】:

我编写了一个连接到服务器并向他发送 ping 命令的应用程序,服务器用 pong 命令回答。

我想实现连接超时机制。我认为它会如下:

  • 客户端发送 ping 并使用 timertask 和延迟启动计时器
  • 当客户端收到 pong 时,timertask 被取消。

另外,我想优化内存。因此,不要在每次发送 ping 命令时重新创建 TimerTask。我尝试下面的代码:

private final Timer mSystemLogoutTimer = new Timer();
private final TimerTask mLogoutTask = new TimerTask() {

    @Override
    public void run() {
        mMessageInterface.onConnectionTimeout();
        cancel();
    }
};

private void ping() {
    sendRequest(RequestBuilder.formPing());
    mSystemLogoutTimer.schedule(mLogoutTask, CoreConst.PING_ANSWER_DELAY);
}

private void onPong() {
    mLogoutTask.cancel();
}

但在尝试第二次安排 TimerTask 时出现以下错误:

java.lang.IllegalStateException: TimerTask is scheduled already
at java.util.Timer.scheduleImpl(Timer.java:572)
at java.util.Timer.schedule(Timer.java:459)

我不明白,因为我在 TimerTask 上调用了cancel()

请告诉我我做错了什么。 谢谢你的回答!

【问题讨论】:

  • mLogoutTask.cancel(); 返回什么?另外,您是否尝试过不使用“内存优化”?
  • 第一次返回true,第二次返回false。
  • 没有“内存优化”一切正常,cancel 总是返回 true
  • 好的,这足以确定我猜发生了什么(见下文)。

标签: android exception timer


【解决方案1】:

TimerTask.cancel() 不一定会阻止任务的执行。根据the SDK documentation,实际阻止执行时返回true,否则返回false

看起来像这样,您的代码在第一次返回 true 时会发生这种情况,但不是第二次,导致在随后调用 Timer.schedule() 时抛出 IllegalStateException

您应该检查TimerTask.cancel() 的返回码,并在返回false 时重新创建您的TimerTaskTimerTask 已被烧毁,无法在该阶段重复使用。

【讨论】:

  • 好的,谢谢!尝试为 Android 编写内存优化代码失败:)
  • 你怎么看,启动timertask来检测ping超时是对的吗?
  • 好吧,关于优化它取决于:一些内存优化有时真的很有用。但是最好先拥有一些可以工作的东西(甚至作为原型),然后尝试以一种消耗尽可能少的 CPU 或内存资源的方式来实现它。前提是收益是相关的。例如,没有必要在每次用户填写表格时会导致 2 毫秒增益的事情上花费数天时间。关于 ping 超时的设计,我没啥好说的,因为不太了解上下文。
  • 谢谢你的解释,我同意你的看法。让我们结束这个讨论:) 再次感谢您!
最近更新 更多