Eclipse中的Run和Debug上的线程run()方法执行不同

Posted

技术标签:

【中文标题】Eclipse中的Run和Debug上的线程run()方法执行不同【英文标题】:Thread run() method execution different on Run and Debug in eclipse 【发布时间】:2015-03-12 22:32:30 【问题描述】:

对于以下程序,在 eclipse 上运行和调试时会出现不同的输出。

 public class MyClass implements Runnable 
        public static void main (String[] args) throws Exception 
            Thread t = new Thread(new MyClass());
            t.start();
            System.out.print("Started");
            t.join();
            System.out.print("Complete");
        
        public void run() 
            for (int i = 0; i < 4; i++) 
                System.out.print(i);
            
        

当作为 java 应用程序运行时,OUTPUT

Started0123Complete

签入时调试模式OUTPUT

0123StartedComplete

有人可以帮忙吗?是因为两个线程吗? main thread 和以t.start() 开头的线程。如果是,那么为什么主线程执行优先级更高?

谢谢

【问题讨论】:

无法保证它将如何在调试/常规模式下运行。如果您在每种模式下多次运行它,您会注意到不同的输出。 我确实尝试了 5,6 次相同的输出。 5 或 6 次没什么,在一个循环中运行 1000 多次,你最终会看到不同的输出 机会:我现在在 1000+ 循环中,但看不出有什么不同 硬件、您的 java 配置、您的操作系统配置有很多变量,您可能只看到 Integer.MAX_VALUE 次中的 1 次之间的差异。对于其他配置,它可能是每 100 次中的 1 次。答案应该澄清为什么会这样。 【参考方案1】:

字符串“Started”和整数的打印顺序未定义。在调用start 之后,不能保证run 方法中的代码将在调用join 之前出现的任何其他语句之前或之后执行。这是多线程应用程序的本质。

您在调试模式和运行模式下看到特定输出的事实可能纯属偶然,如果您多次运行代码或在不同平台/JVM 版本上运行代码,可能会发生变化。如果在这种情况下您需要确定性顺序,那么实现它的唯一方法是在调用 start 之前打印一个字符串 before 或引入某种其他类型的信号量来强制线程等待主线程反之亦然。

【讨论】:

实际上这不是您可以实现它的 /only/ 方式,子线程和父线程之间的某种共享互斥锁也可以让您这样做,例如信号量 @MrWiggles touche,修改了我的答案!【参考方案2】:

这是巧合。您无法控制线程调度程序。

但是,在调试环境中,debugger 会插入您的代码以检查值和执行情况。这种检查增加了每个线程时间片完成的工作量。

例如,在常规运行中,主线程可能只需要 1 个时间片来创建新的线程对象、启动它并打印Started 消息。然后会发生上下文切换,第二个线程将有机会工作。在调试运行中,主线程只有足够的时间来创建新的线程对象并启动相应的线程。然后会发生上下文切换,另一个线程会做它的事情。

【讨论】:

将接受的答案更改为此,因为这更有意义。【参考方案3】:

与是否处于调试模式无关。 无法保证何时执行

System.out.print("Started"); //this is in the main thread

相比

for (int i = 0; i < 4; i++)  // this is in the started thread
            System.out.print(i);
        

甚至可以

01Started23Complete

【讨论】:

我喜欢你展示了循环中途停止的可能性。【参考方案4】:

是的,因为有 2 个线程,但是输出是不可预测的。 不,主线程没有获得高优先级,因为它的 MAIN。 在多线程中你不能说任何特定的交错执行。

在 Debug 中,我的猜测是您为主线程设置了一个断点,以便它等待,同时其他线程可能已经执行。

【讨论】:

可能是这种情况:) 有没有文章可以帮助更多地理解这一点?如果这真的像你说的那样发生。【参考方案5】:

在两个(运行/调试)模式输出将是

开始0123完成

您会看到结果 0123StartedComplete,因为您必须在主线程代码中有调试点,这就是原因。

如果您想更好地理解,请将 run() 方法移至 MyClass 内部,并将调试器点放在 run 方法中,现在您将看到它打印为 Started0123Complete

在内部,主线程正在创建子线程“t”,当 t.start() 被调用时,它正在等待捕获线程执行的监视器(即 run()),当您在主线程中添加调试语句时,子线程正在进入监视器并执行运行方法,一旦完成,主线程将再次启动。

【讨论】:

这家伙其实是对的……run方法已经在课堂上。我只是将调试点改成运行,但我想了解内部发生了什么 在内部,主线程正在创建子线程“t”,当 t.start() 被调用时,它正在等待捕获线程执行的监视器(即 run())以及添加调试时主线程中的语句,子线程进入monitor并执行run方法,一旦完成,主线程再次启动。

以上是关于Eclipse中的Run和Debug上的线程run()方法执行不同的主要内容,如果未能解决你的问题,请参考以下文章

C++中调试(debug) 和 运行(run)有啥区别吗?

我的eclipse只能run不能debug

eclipsemain直接run报错debug正常

IDEA ECLIPSE Debug 卡住,Run正常

解决eclipse Run启动或Debug时Console控制台不自动弹出问题

eclipse中的web project项目运行 Run As → 1 run on server 出现图上的情况