我正在研究ArcGIS地图实施中的一个奇怪的错误。最近,我注意到当我在某个地方放置断点并在调试模式下运行应用程序时,我们的软件正常工作(可能我们面临并发/线程问题)。断点被击中后,我立即(1-2秒)恢复应用程序,地图上的所有内容都完美呈现。 但是,当我用Thread.sleep(2000)替换断点时;并运行应用程序,错误仍然存在。
对我而言,这真的很奇怪,我认为两件事情都会完全一样。断点设置为“Suspend Thread”,我使用Eclipse IDE。
将线程放入睡眠状态和挂起Java中的线程有什么区别?
修改 我不要求这个特定的bug解决方案。我只是想知道在这两种情况下执行程序的区别是什么:
案例1
案例2
此处粘贴代码没有任何区别,因为我没有询问任何特定的代码执行场景,我只是对JVM是否以与处理Thread.sleep()相同的方式处理断点感兴趣。 线程在特定时间内进入休眠状态时JVM中发生了什么?当线程被挂起(通过命中断点)时JVM中发生了什么?有什么不同吗?
答案 0 :(得分:2)
存在一些相当大的差异,是的。
Thread.sleep请求操作系统从CPU调度中删除n毫秒的线程。请注意,这种影响是特定于操作系统的,并且主要限于一个线程。
输入断点需要激活JVM的调试模式,这会影响整个JVM的行为,从而影响时间/比赛。 AMD有documented the performance effects of putting the JVM into debug mode。效果确实有所不同,其中很多都是JVM和调试器之间的通信,并限制了JVM在调试模式下允许的优化。最极端的例子是不让JVM对某些方法使用本机字节代码,从而迫使它使用速度慢得多的解释器。但是,从这个问题的角度来看,最重要的区别是调试器提供了暂停单个线程或多个线程的能力。
请求进入休眠状态的线程与导致另一个线程被阻塞的线程之间存在很大差异。在Java中,它需要线程之间的协作来停止线程,即使对于断点也是如此。在断点的情况下,JVM会为我们完成协作,它只在线程到达安全点时才会发生。安全点不会出现在每一行代码中,因此会非常强烈地影响竞争条件,因为JVM必须等待线程到达安全点才能暂停并且调试器可以接管。安全点通常发生在方法调用和循环的后沿(但并非总是)。
答案 1 :(得分:0)
我认为暂停将强制您使用Thread.resume()
重新激活Thread
,而如果使用Thread.sleep()
则不必这样做。
在API中,关于resume()
:“此方法将线程置于挂起状态,并且可以使用resume()
方法恢复。”
睡眠只会阻止它,但是你不必再次激活它。
希望它有所帮助。
Clemencio Morales Lucas。