gpt4 book ai didi

Java 线程 - start() 和 run() - 在控制台中丢失行

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:42:34 24 4
gpt4 key购买 nike

为什么在下面的场景 1 中缺少另一个“TaskImpl run()”?

场景 1:如果标有 1. 的行在标有 2. 的行之前,则在控制台中显示为:

TaskImpl run()
ThreadImpl run()
ThreadImpl run()
Finished

场景 2:如果标有 2. 的行在标有 1. 的行之前,则在控制台中显示为:

TaskImpl run()
TaskImpl run()
ThreadImpl run()
ThreadImpl run()
Finished

我的代码:

public class ThreadTest {
public static void main(String[] args)
{
Thread t1 = new ThreadImpl();
Thread t2 = new Thread(new TaskImpl());

t1.start();
t2.start();

t1.run(); // 1.
t2.run(); // 2.

try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println("Finished");
}
}

class ThreadImpl extends Thread {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("ThreadImpl run()");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

class TaskImpl implements Runnable {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("TaskImpl run()");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

最佳答案

正如您在 Thread#run 的实现中看到的那样targetrun 方法(应该在线程中运行的 Thread 实现/子类)只有在 target 不是 null:

@Override
public void run() {
if (target != null) {
target.run();
}
}

现在另一个信息:如果一个线程完成了它的工作,它会调用 private exittarget 设置为 null (*) 的方法:

private void exit() {
// [omitted code lines]

/* Aggressively null out all reference fields: see bug 4006245 */
target = null;

// [omitted code lines]
}

因此,如果您在 Thread 上调用了 start 并且它已经完成了它的工作,那么您就不能再调用 run 了……当然可以,但是我赢了做很多事。

现在让我们看看您的代码的第一个版本:

t1.start(); -> starts a thread; takes at least 2 seconds to finish
t2.start(); -> starts a thread; takes at least 1 second to finish

t1.run(); -> blocks main thread; takes at least 2 seconds to finish
t2.run(); -> called after `t1.run()` finished;

如您所见,t2.run() 将在 t2.start() 之后至少运行 2 秒,因为 t1.run() 阻止方法调用。所以 t2(来自 t2.start())已经完成并将 target 设置为 null 所以 t2 .run() 未通过 target != null 检查并且“什么都不做”。

现在是第二个版本:

t1.start(); -> starts a thread; takes at least 2 seconds to finish
t2.start(); -> starts a thread; takes at least 1 second to finish

t2.run(); -> blocks main thread; takes at least 1 seconds to finish
t1.run(); -> called after `t2.run()` finished;

这里 t2.run() 可以在 t2.start()t2 完成他的“ sleep ”之前运行,所以 target 仍然设置正确。
t1.run()也没有问题,因为它直接调用了ThreadImploverridenrun方法,所以它不需要通过检查。而且无论如何传递它都不会有问题,因为 t2.run() 会 hibernate 1 秒,所以 t1 来自 t1.start() 又睡了一秒钟,他的 target 也仍然设置。
这就是您获得“完整”输出的原因。

我希望我的解释很清楚,并且您了解不同输出的原因:)。

(*) 请注意,此行为在其他 Java 环境中可能会有所不同。但是 Oracles 版本和 OpenJDK 正在这样做。

关于Java 线程 - start() 和 run() - 在控制台中丢失行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31473149/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com