【问题标题】:Infinite function call, Recursion or Timer?无限函数调用,递归还是定时器?
【发布时间】:2011-11-16 14:41:04
【问题描述】:

我正在开发一个 Java 函数,它应该被称为 infinitely。此函数将调用 Web 服务,该服务将返回返回结果。然后对结果进行解析分析

在网络服务返回结果之前,不应再次调用函数,并且分析这些结果

我应该使用无限递归来实现这一点吗?或者我应该使用在特定时间间隔调用该函数的计时器?

也出现了一些问题:

  1. 如果 Web 服务的响应超时会怎样?如何防止应用程序崩溃或无限次调用而无响应?

  2. 我应该创建一个事件驱动类来处理这些请求吗?

  3. 在优化方面,哪种方案效率更高?

-- 编辑

我知道这个问题有点模糊和笼统,所以不详细的答案就可以了,我将专注于实施。我只需要有关方法的建议。 :)

感谢任何帮助。

【问题讨论】:

  • “我应该使用无限递归来实现这一点吗?” - 著名的遗言。
  • Java 中的递归深度问题呢?

标签: java web-services recursion timeout


【解决方案1】:

您几乎可以肯定不应该对没有明确“基本情况”的进程使用递归。无限递归是一个非常糟糕的主意。每次调用都会占用越来越多的堆栈,最终您将死于 OOM 错误(或堆栈溢出,如果 Java 区分这两者)。

你可以试试

private Object mutex = new Object();
private boolean yourTaskIsRunning = false;

protected void yourTask()
{
    synchronized(mutex)
    {
        if (yourTaskIsRunning) return;
        yourTaskIsRunning = true;
    }
    try
    {
        // do your thing
    }
    finally
    {
        yourTaskIsRunning = false;
    }
}

或者,如果您可以将您的任务捆绑到一个不同的对象中,请将其是否为 null 用作“任务正在运行”标志。在第一个 synchronized 部分中创建对象,在“做你的事情”部分中启动它,并在 finally 块中将其设置为 null。 (请注意,无论哪种方式,您都需要确保通过函数的所有非致命路径——甚至抛出异常!——完成后“清除标志”。因此finally 块。)

无论哪种方式,您都可以设置一个计时器来调用此函数,如果它已经在运行,它将立即返回。计时器方法的唯一缺点是,在一个呼叫结束和下一个呼叫开始之间可能会有一些停机时间。

【讨论】:

  • 有趣的同步语句似乎是个好主意。这会防止函数调用重叠吗?
  • synchronized 块在这里有一个很大的目的:它保持两个同时调用函数的成功(因为一次只能持有一个锁)。第一个调用将开始运行,第二个调用将被阻塞,直到第一个调用已经开始(并适当地设置标志)。它会看到标志集,知道函数已经在使用,并立即返回。其次,它做了一些缓存魔法,以确保调用该函数的其他线程看到标志的真实值(而不是他们之前可能缓存的旧副本)。
【解决方案2】:

我很困惑。为什么需要计时器?

似乎调用是同步的,即下一个调用不会触发,直到您收到第一个调用的响应。

为什么不只是一个简单的 while 循环,其中包含一个 try/catch 块来捕获 java.net.SocketTimeoutException 并在一定数量的失败时退出循环?

建议的递归对于这个用例来说似乎是个坏主意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多