奇怪的Java问题,而循环终止
我有一段代码,看起来像这样:在我的网格类)奇怪的Java问题,而循环终止
Algorithm a = null;
while(a == null)
{
a = grid.getAlgorithm();
}
信息getAlgorithm(这取决于用户从某些选项选择算法的某些亚型返回。
我的问题是,即使在选择算法后,循环也不会终止。但是,如果我只是放置一个System.out.println(“Got here”),那并不是棘手的问题。在我调用getAlgorithm()之后,程序运行得非常好,循环终止了。
我的问题是:为什么添加那个magic print语句突然让循环终止?
此外,当我开始使用我的新笔记本电脑时,这个问题首次出现,我怀疑这是相关的,但我认为这值得一提。
编辑:有问题的程序不是多线程的。 getAlgorithm()的代码是:
public Algorithm getAlgorithm()
{
return algorithm;
}
其中算法最初为空,但会在某些用户输入时更改值。
您正在进行活动轮询。这是一个不好的做法。你应该至少让轮询线程睡眠(使用Thread.sleep)。由于println做了一些io,它可能就是这么做的。如果你的应用不是多线程的,那么它根本不可能工作。
你怎么知道这是主动投票?谁知道getAlgorithm()里面发生了什么? OP没有告诉我们。也许每次调用都会改变'grid',所以每个调用可能会返回一个不同于前一个值的值。 – 2011-03-13 03:55:40
op的说明表示等待用户输入。这个问题似乎是一个同步问题。特拉维斯似乎同意。像这样在一个循环中变换一个网格,即一个UI对象将是一个糟糕而混乱的做法。听起来像是一个公平的赌注给我。 – 2011-03-13 03:59:07
有趣的是,我的旧电脑上的代码运行正常,但在我的新电脑上运行它会产生这种特殊的错误。所以我知道理论上的代码应该工作。 – Deomachus 2011-03-13 04:01:06
如果此循环等待GUI中的用户输入,那么ouch。坏,坏主意,甚至Thread.sleep()
补充说我永远不会推荐它。相反,你很可能想要在有问题的组件上注册一个事件监听器,并且只有当内容改变时才会触发验证代码。
由于您已经达到了某种形式的死锁,尤其是在您的应用程序是多线程的情况下,您的程序锁定的可能性很大。我不会试图解决这个问题并且绕开它,我会认真考虑重新设计应用程序的这部分工作方式。
如果他的循环写成:'while(!line.equals(“stop”)){line = getNextLine(); '',你会称这是一个“坏主意”吗?我在这里没有看到任何区别。 – 2011-03-13 04:10:51
我编辑了我的帖子,使其更清晰,但我的意思是他是否在某种形式的GUI上进行轮询,这是一个糟糕的主意。与getNextLine()不同的是,你实际上每次都会获得新的东西。 – berry120 2011-03-13 04:18:40
OP写道:“我的网格类中的getAlgorithm()返回算法的一些子类型,取决于用户从某些选项中选择的内容。”听起来像一个荣耀的'getNextLine()'给我。 **但**基于OP的编辑(在我的评论之后完成),我同意这里存在线程问题。 – 2011-03-13 17:23:43
您应该检查getAlgorithm()方法中是否存在错误。
我认为这个问题必须处理如何执行grid.getAlgorithm。如果执行该方法的代价很小,那么只要方法继续返回null,while循环就会非常快速地循环。这通常被称为busy wait。
现在听起来好像您的新笔记本电脑遇到starvation问题,该问题并未在您的旧电脑上显示。很难说为什么,但如果你看看我上面提到的链接,维基百科的文章确实表明忙碌的等待确实有不可预知的行为。也许你的旧电脑比你的新电脑更好地处理用户IO。无论如何,在您的新笔记本电脑上,该环路正在将资源从处理您的用户IO的任何东西中分离出来,因此它正在扼制负责打破环路的流程。
有两种情况:
- 你的代码是真的不意味着是多线程的。在这种情况下,您需要在循环中插入某种用户输入。否则,你可能会留下它作为算法a = grid.getAlgorithm();并防止无限循环。
- 你的代码是多线程的,在这种情况下你有某种'可见性'问题。请转至Atomicity, Visibility and Ordering或阅读Java Concurrency in Practice以了解有关可见性的更多信息。从本质上讲,这意味着如果没有线程之间的某种同步,您正在循环的线程可能永远不会发现由于JVM可能执行的优化而发生的值已更改。
您没有提及任何有关此代码运行的上下文。如果它是一个基于控制台的应用程序,并且你从一个'main'函数开始,你会知道是否有多线程。因为你说没有多线程,我认为情况并非如此。另一种选择是,这是一个摆动应用程序,在这种情况下,您应该阅读Multithreaded Swing Applications。这可能是一个Web应用程序,在这种情况下,可能会出现类似的情况。
在任何情况下,您都可以调试应用程序以查看哪个线程正在写入“算法”变量,然后查看哪个线程正在读取它。
我希望这是有帮助的。无论如何,如果您在问题中提供更多的上下文,您可能会找到更多帮助。特别是对于一个像'怪异的Java问题,循环终止'这样有趣的标题的问题。
哦,亲爱的请告诉我,您在等待用户输入时不会像这样循环... – 2011-03-13 03:49:22
发生这种情况的唯一方法就是如果返回null。如果它不为null,则循环将退出。检查'getAlgorithm()'的来源或在循环中打印出它的内容以确认它不为空。 – berry120 2011-03-13 03:52:17
@Travis - 看起来更像是一个迭代器,对第一个非空算法进行线性搜索。但是谁知道? – 2011-03-13 03:52:42