线程 运行() 方法在 运行 上的执行与 eclipse 中的调试不同
Thread run() method execution different on Run and Debug in eclipse
对于以下程序,运行 和在 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()
开头的线程。如果是,那么为什么主线程执行优先完成?
谢谢
字符串"Started"和整数的打印顺序未定义。调用 start
后,无法保证 run
方法中的代码将在调用 join
之前出现的任何其他语句之前或之后执行。这是多线程应用程序的本质。
您在调试模式与 运行 模式下看到特定输出的事实可能纯粹是偶然的,如果您多次 运行 您的代码或在不同的 platforms/versions虚拟机。如果在这种情况下需要确定性顺序,实现它的唯一方法是在 调用 start
之前打印一个字符串 或引入某种其他类型的信号量来强制线程等待主线程或反之亦然。
这是巧合。您无法控制线程调度程序。
但是,在调试环境中,debugger 会插入您的代码以检查值和执行。此检查增加了每个线程时间片完成的工作量。
例如,在常规运行中,主线程可能只需要1个时间片来创建新的线程对象,启动它,并打印Started
消息。然后将发生上下文切换,第二个线程将有机会工作。在调试 运行 中,主线程只有足够的时间来创建新的线程对象并启动相应的线程。然后会发生上下文切换,另一个线程会做它的事情。
是的,因为有 2 个线程,但是输出是不可预测的。
不,主线程没有获得高优先级,因为它是 MAIN。
你不能在多线程中说任何特定的交错执行。
在 Debug 中,我的猜测是你为主线程设置了一个断点,所以它等待,同时另一个线程可能已经执行。
与是否处于调试模式无关。
无法保证何时执行
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
在两个(运行 / 调试)模式输出将是
开始0123完成
您看到结果 0123StartedComplete,因为您必须在主线程代码中设置调试点,这就是原因。
如果您想更好地理解,请将 运行() 方法移动到 MyClass 内部并将调试器点放在 运行 方法中,现在您将看到它打印为 开始0123完成.
在内部,主线程正在创建子线程“t”,当调用 t.start() 时,它正在等待捕获线程执行的监视器(即 运行()),当您正在主线程中添加调试语句,子线程正在进入监视器并且正在执行 运行 方法,一旦完成,主线程将再次启动。
对于以下程序,运行 和在 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()
开头的线程。如果是,那么为什么主线程执行优先完成?
谢谢
字符串"Started"和整数的打印顺序未定义。调用 start
后,无法保证 run
方法中的代码将在调用 join
之前出现的任何其他语句之前或之后执行。这是多线程应用程序的本质。
您在调试模式与 运行 模式下看到特定输出的事实可能纯粹是偶然的,如果您多次 运行 您的代码或在不同的 platforms/versions虚拟机。如果在这种情况下需要确定性顺序,实现它的唯一方法是在 调用 start
之前打印一个字符串 或引入某种其他类型的信号量来强制线程等待主线程或反之亦然。
这是巧合。您无法控制线程调度程序。
但是,在调试环境中,debugger 会插入您的代码以检查值和执行。此检查增加了每个线程时间片完成的工作量。
例如,在常规运行中,主线程可能只需要1个时间片来创建新的线程对象,启动它,并打印Started
消息。然后将发生上下文切换,第二个线程将有机会工作。在调试 运行 中,主线程只有足够的时间来创建新的线程对象并启动相应的线程。然后会发生上下文切换,另一个线程会做它的事情。
是的,因为有 2 个线程,但是输出是不可预测的。 不,主线程没有获得高优先级,因为它是 MAIN。 你不能在多线程中说任何特定的交错执行。
在 Debug 中,我的猜测是你为主线程设置了一个断点,所以它等待,同时另一个线程可能已经执行。
与是否处于调试模式无关。 无法保证何时执行
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
在两个(运行 / 调试)模式输出将是
开始0123完成
您看到结果 0123StartedComplete,因为您必须在主线程代码中设置调试点,这就是原因。
如果您想更好地理解,请将 运行() 方法移动到 MyClass 内部并将调试器点放在 运行 方法中,现在您将看到它打印为 开始0123完成.
在内部,主线程正在创建子线程“t”,当调用 t.start() 时,它正在等待捕获线程执行的监视器(即 运行()),当您正在主线程中添加调试语句,子线程正在进入监视器并且正在执行 运行 方法,一旦完成,主线程将再次启动。