Java:调用自我调用方法而不冻结?

时间:2011-09-22 20:45:38

标签: java swing concurrency

所以这真的很复杂,我花了一段时间才意识到实际发生了什么。希望你比我更了解它。

我有一个显示GUI的Swing类。在GUI中我有一个按钮,在Swing类中我有一个方法,只要我点击按钮就会调用它。

当调用该方法时,我在名为“Manager”的对象中调用另一个方法。然后,管理器中的方法调用名为“Core”的类中的另一个方法。 Core中的那个方法设置了一个局部变量,然后在Core中调用另一个自调用的方法。

问题在于,因为它是自我调用的,它永远不会停止运行,对吧?并且因为它永远不会停止运行,所以没有任何东西返回到Core中的第一个方法。并且由于没有返回到该方法,因此也没有任何内容返回给Manager。由于永远不会调用该方法,因此GUI类永远不会得到响应,这会使GUI冻结。

对于凌乱的描述非常抱歉。不幸的是我无法发布代码。我希望任何人都明白我的意思,某人之前必须遇到同样的问题。

谢谢!

编辑:

我忘了提到Core类是一个帖子。

6 个答案:

答案 0 :(得分:3)

您长时间运行的进程阻止主Swing线程,EDT或事件派发线程继续,这将使您的GUI完全无响应。解决方案是在后台线程中执行任何长时间运行的进程,例如由SwingWorker对象创建的进程。请查看名为Concurrency in Swing的链接,了解有关使用SwingWorker对象的更多信息。

答案 1 :(得分:3)

自我调用称为递归。这是一种强大的技术,但如果你不小心,可能导致无限循环(悬挂)。您需要确保每次递归(即每次方法调用自身时)某些内容都会更改为终止状态。例如,您可以使用保证减少每次递归的数字,并将退出条件设置为您的数字为负数。另一个例子是你递归地“吃掉”了一些数据结构,让我们说一个字符串,直到什么都没有留下。通常这种“向终止状态改变的东西”作为参数传递给方法。你的递归方法应该从一个检查开始:我的参数是否处于终止状态?如果是,则终止,如果不是,则执行魔术。

其次,使用Swing,你应该小心不要违反它的架构。它不是真正的MVC,而是一个2层框架。如果您对如何使用Swing感兴趣,我建议您阅读MVC等设计模式。

答案 2 :(得分:2)

你遇到了很多问题。

1)您的递归函数需要退出条件。像

这样的东西
public int imRecursive(int arg) {
   if (arg > 100) return;
   imRecursive(arg++);    
}

在该示例中,imRecursive不会被反复调用,一旦arg达到100就会停止。

2)使用swing应用程序,只有GUI相关代码才能在主事件派发线程中运行。如果你的递归方法是长时间运行的,你应该使用SwingWorker在另一个线程中执行它,这样你的GUI就不会锁定。

答案 3 :(得分:1)

发布一些代码。你说Core是一个Thread,我认为这意味着class Core extends Thread但是我们需要看看你在哪里产生一个新线程(调用扩展Thread的类中的方法不会使它运行在一个单独的线程中。)

你的递归(自调用)方法,如果它永远不会破坏递归,则会在很长时间内导致StackOverflowError。如果你没有得到它,那么要么你没有使用递归函数或在某处破坏递归。编写永不终止的方法的正确方法是 not 递归,它是迭代。

GUI冻结几乎可以肯定是因为在GUI线程中发生了一些耗时的处理,还有一个理由认为Core中的方法没有在单独的线程中运行。

答案 4 :(得分:0)

我不明白为什么你必须自我调用你的方法......

你试图做一些递归吗?

如果方法永远不会结束,你会得到一个无限循环,它不好。

根据您的尝试,您可以使用Java线程,或重新考虑您的代码..我打赌您做错了。

答案 5 :(得分:0)

你需要分析你的自调用方法调用 - 这是一个递归调用 - 但是每个递归方法都必须有一些条件来阻止递归 - 检查在你的情况下你应该得到这样一个条件的条件