2

我有一段看起来像这样的代码:

Algorithm a = null;  
while(a == null)  
{  
    a = grid.getAlgorithm();  
}  

我的 Grid 类中的 getAlgorithm() 根据用户从某些选项中选择的内容返回算法的某些子类型。

我的问题是,即使选择了算法,循环也永远不会终止。但是,如果我简单地放置一个 System.out.println("Got here"); 在我调用 getAlgorithm() 之后,程序运行得非常好,并且循环按预期终止。

我的问题是:为什么添加那个神奇的打印语句会突然使循环终止?

此外,当我开始使用我的新笔记本电脑时,这个问题首次出现,我怀疑这是否相关,但我认为值得一提。

编辑:有问题的程序不是多线程的。getAlgorithm() 的代码是:

public Algorithm getAlgorithm ()  
{  
    return algorithm;  
}

其中 algorithm 最初为 null,但会在某些用户输入时更改值。

4

5 回答 5

2

我相信这个问题必须处理 grid.getAlgorithm 的执行方式。如果与执行该方法相关的成本非常低,那么只要该方法继续返回 null,您的 while 循环就会非常快速地循环。这通常被称为忙等待

现在听起来您的新笔记本电脑遇到了饥饿问题,而这并没有在您的旧电脑上表现出来。很难说为什么,但是如果您查看我上面包含的链接,维基百科的文章确实表明忙碌的等待确实具有不可预测的行为。也许您的旧计算机比您的新笔记本电脑更好地处理用户 IO。无论如何,在您的新笔记本电脑上,该循环正在从处理您的用户 IO 的任何内容中占用资源,因此它使负责中断循环的进程处于饥饿状态。

于 2011-03-13T04:32:55.457 回答
1

您正在进行主动轮询。这是一个不好的做法。您至少应该让轮询线程休眠(使用 Thread.sleep)。由于 println 做了一些 io,它可能就是这样做的。如果您的应用程序不是多线程的,那么它根本不可能工作。

于 2011-03-13T03:51:22.527 回答
1

如果这个循环是在 GUI 中等待用户输入,那么哎哟。坏的,坏的主意,即使Thread.sleep()添加了我也不会推荐它。相反,您很可能希望在相关组件上注册一个事件侦听器,并且仅在内容更改时触发验证代码。

您的程序很可能被锁定,因为您已经达到某种形式的死锁比其他任何事情都多,特别是如果您的应用程序是多线程的。与其尝试解决这个问题并破解它,我会认真考虑重新设计这部分应用程序的工作方式。

于 2011-03-13T03:58:22.593 回答
0

您应该检查 getAlgorithm(),该方法一定有问题。

于 2011-03-13T04:08:32.240 回答
0

有两种情况:

  1. 您的代码实际上并不意味着是多线程的。在这种情况下,您需要在循环中插入某种用户输入。否则,您不妨将其保留为 Algorithm a = grid.getAlgorithm(); 并防止无限循环。
  2. 您的代码是多线程的,在这种情况下您会遇到某种“可见性”问题。转到原子性、可见性和排序或阅读Java 并发实践以了解有关可见性的更多信息。从本质上讲,这意味着如果线程之间没有某种同步,您正在循环的线程可能永远不会发现该值由于 JVM 可能执行的优化而发生了变化。

您没有提及有关如何运行此代码的任何上下文。如果它是基于控制台的应用程序并且您从“主”功能开始,您就会知道是否存在多线程。我假设情况并非如此,因为您说没有多线程。另一种选择是这是一个摇摆应用程序,在这种情况下您应该阅读多线程摇摆应用程序。它可能是一个 Web 应用程序,在这种情况下,类似的情况可能适用于 swing。

在任何情况下,您总是可以调试应用程序以查看哪个线程正在写入“算法”变量,然后查看哪个线程正在从中读取。

我希望这是有帮助的。无论如何,如果您在问题中提供更多背景信息,您可能会找到更多帮助。特别是对于标题为“奇怪的 Java 问题,while 循环终止”这样有趣的问题。

于 2011-03-13T21:17:13.220 回答