【问题标题】:Method should call once and only once in its lifecycle方法应该在其生命周期中调用一次且仅调用一次
【发布时间】:2012-04-14 00:58:39
【问题描述】:

我有一个方法,它实际上是一个调度程序,它每隔一小时运行一个进程并每小时创建一个日志文件。
我想在应用程序生命周期中调用一次此方法,因此我从静态块中调用它。
但我觉得这不起作用,因为文件有时会在一小时内生成,有时会提前生成。我在某处听说静态块只执行一次,这不是真的吗?
如果是,那我该怎么办?

【问题讨论】:

  • 您使用的是应用程序容器吗?像 Weblogic 这样的一些容器可以让你定义启动任务,让你在没有类加载器问题的情况下执行作业(正如 jabal 所说)。

标签: java static classloader application-lifecycle


【解决方案1】:

你也需要一个变量。

class ...

  private static hasRun = false;

  public static synchronize boolean runOnce ()
  {
     if (hasRun) return false;

     hasRun = true;
     // do something
     return true;
  }

在不使用此类时,可能永远不会调用静态块。

有一个关于卸载类的讨论 Unloading classes in java?

当卸载类发生时,可能会发生多次加载而不是多次调用静态初始化程序。但是,在这种情况下,我的解决方案将失败,因为在这种情况下,任何解决方案都必须失败。

我觉得这非常罕见且不太可能。但也许你必须在你不控制环境的情况下处理

【讨论】:

  • 静态块不是静态方法
  • 没错,但是当类被使用时会执行一个静态块。这个问题听起来并不要求这个
  • 他说“所以我把它放在静态块中。”
  • 那是他所做的,不一定是他想要达到的
  • 顺便说一下,Oracle/sun 的正确术语是:静态初始化块。所以“静态块”也可以解释为一组静态“成员”
【解决方案2】:

静态初始化块仅在类加载器加载类时执行一次。它们执行的时间与您的应用程序逻辑如此密切相关。更准确地说,不同的类加载器可能会加载您的类,因此静态块理论上可以执行多次。

出于调度目的,请尝试使用开箱即用的调度程序库,例如 Quartz 调度程序。 (http://quartz-scheduler.org) 第一次这可能看起来有点开销,但是这些库提供了您最终可能需要的高级功能。只是一个简单的例子:如果你的程序在一小时内停止并重新启动怎么办?然后该过程可能会在这个特定小时内运行两次。使用石英,您也可以处理这种情况。

【讨论】:

  • 感谢 jabal,但我使用的是石英调度器,之后遇到了这个问题:)
  • 也许你应该就石英问题提出一个不同的问题。可能您只是没有正确使用,因为它是数百万人使用的非常高质量的产品。我很确定社区可以为您提供帮助。
【解决方案3】:

静态方法并不意味着它只运行一次。 static 意味着它可以在不实例化类实例的情况下访问外部方法。

我想不到的最佳解决方案。有一个静态变量,以便它可以与您的静态方法一起刷新,并在该方法执行后立即增加该静态变量。每次执行此方法时,检查该变量,如果它已经增加,则立即退出。

【讨论】:

  • 静态块不是静态方法
  • 我相信并引用 I have a method,这是 OP 在这里声明的第一件事。
  • 我同意您的解决方案,但有两个 cmets:a)您的第一段似乎是错误的,问题是指类中的静态代码块,而不是静态方法。 b) 什么是静态类
  • 我有一个方法是对的,但是我从静态块老兄中调用了这个方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-20
  • 2020-09-19
  • 1970-01-01
  • 2021-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多