【问题标题】:What's the intention of using timer like this? [duplicate]像这样使用计时器的目的是什么? [复制]
【发布时间】:2013-07-12 08:20:47
【问题描述】:

我不明白为什么在下面的代码中使用这样的计时器变量。

问题一:在startTimer()和stopTimer()中,都有一个局部变量aTimer要在对定时器的操作之前使用,目的是什么?

问题2:在stopTimer()中,timer会被赋值为null,所以如果timer不为null,则表示该timer已经创建,当调用startTimer()时,timer不会被再次创建。这是检查计时器是否正在运行的最佳做法吗?通过将 null 分配给计时器,PMD 还会报告“NullAssignment”违规

private Timer timer;

private void startTimer() {
  if (timer == null) {
    Timer aTimer = timerFactory.createTimer(100000, null);
    aTimer.setListener(this);
    timer = aTimer;
  }
}

private void stopTimer() {
  if (timer != null) {
    Timer aTimer = timer;
    timer = null;
    aTimer.cancel();
    aTimer.setListener(null);
 }
}

public void start() {
  synchronized(..) {
     startTimer();
  }
}

public void stop() {
 synchronized(..) {
     stopTimer();
 }
}

【问题讨论】:

  • 不,不是。 “如何修复 pmd 违规“NullAssignment”?是我问的,但方向错误。谢谢。
  • 什么方向?这两个问题都是您向我们提出的……
  • 上一个问题导致解释了为什么 PMD 报告 Nullassignment 和 GC 收集。请在这个问题的问题 1 和问题 2 中找到我真正关心的问题
  • 如果你重构,你应该考虑使用ScheduledExecutorService来代替——Timer has an undocumented "feature" which is dangerous,而且ScheduledExecutorService更容易使用
  • @fge 我不会称之为危险 - 这可能是设计使然(在下午 3 点运行任务不应该在下午 2 点运行,因为时钟已经改变) - 但 ScheduledExecutorService 无论如何都更强大。

标签: java refactoring


【解决方案1】:

您的代码相当于:

private boolean started = false;
private Timer timer;

public synchronized void start() {
    if (!started) {
        timer = timerFactory.createTimer(100000, null);
        timer.setListener(this);
        started = true;
    }
}

public synchronized void stop() {
    if (started) {
        timer.cancel();
        timer.setListener(null);
        started = false;
    }
}

更短更容易理解(恕我直言)。局部变量是多余的,因为您的代码是同步的,并且您的 timer 变量不能被两个线程同时访问。

并且使用timernull 的事实作为启动/未启动的标志对于这么短的代码很好,但是随着添加更多行,它会变得混乱。我更喜欢一个适当的 started 标志,它是不言自明的。

【讨论】:

  • 谢谢@assylias。这是我预期的答案,合理且有帮助。
【解决方案2】:

我的假设是这个对象的原作者想要封装 Timer 对象,这样你就不会在 start() 和 stop() 之间错误地重新创建它。

这并没有直接的附加价值,但如果与一大群人一起处理经常使用的对象,可能是为了防止不必要的访问弄乱信息,或其他什么。

【讨论】:

    【解决方案3】:

    定时器是同步的,以防止线程干扰和内存一致性错误。同步定时器意味着:

    • 没有来自其他线程的线程干扰
    • 确保内存一致性
    • 确保对定时器的原子访问,其中定时器的外部线程无法访问定时器的中间状态。即要么完成动作,要么根本没有动作。

    【讨论】:

      猜你喜欢
      • 2014-06-24
      • 1970-01-01
      • 2018-09-23
      • 2011-08-15
      • 1970-01-01
      • 2011-09-14
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多