Java线程-start()和run()-控制台中的行丢失
为什么下面场景1中缺少另一个“taskinpl run()” 场景1:如果行标记为1。在标有2的行之前。这在控制台中显示: taskinpl run()Java线程-start()和run()-控制台中的行丢失,java,multithreading,Java,Multithreading,为什么下面场景1中缺少另一个“taskinpl run()” 场景1:如果行标记为1。在标有2的行之前。这在控制台中显示: taskinpl run() ThreadImpl run() ThreadImpl run() 完成 场景2:如果标记为2的行。在标有1的行之前。这在控制台中显示: taskinpl run() taskinpl run() ThreadImpl run() ThreadImpl run() 完成 我的代码: public class ThreadTest { p
ThreadImpl run()
ThreadImpl run()
完成 场景2:如果标记为2的行。在标有1的行之前。这在控制台中显示: taskinpl run()
taskinpl run()
ThreadImpl run()
ThreadImpl run()
完成 我的代码:
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();
}
}
}
正如您在
target
的run
方法的实现中所看到的(应该在线程中运行的Thread
实现/子类),只有在target
不是null
时才会调用它:
现在另一个信息:如果线程完成了它的工作,它将调用将target
设置为null
(*)的方法:
因此,如果您在一个线程上调用了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
Sot2.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
t2.run(); -> blocks main thread; takes at least 1 seconds to finish
t1.run(); -> called after `t2.run()` finished;
这里t2.run()
可以在t2
之前运行t2.start()
可以完成他的“睡眠”,因此target
仍然设置正确。而
t1.run()
也没有问题,因为它直接调用ThreadImpl
的重写run
方法,所以不需要通过检查。无论如何,通过它也不会有问题,因为t2.run()
睡眠1秒,所以t1.start()
中的t1
仍然睡眠1秒,他的目标也仍然设置。
这就是您获得“完整”输出的原因
我希望我的解释清楚,并且您理解不同输出的原因:)
(*)请注意,这种行为在其他Java环境中有所不同。但是Oracles版本和OpenJDK正在这样做。在您的代码中,您在哪里打印过taskinpl run()
?我看不到这一点。这里@TimBiegeleisen:class ThreadImpl扩展了Thread{@Override public void run(){try{Thread.sleep(2000);**System.out.println(“ThreadImpl run()”);**
为什么要直接调用Thread.run()
?发生这种情况是因为t1.run()
比t2.start();
花费的时间更多。检查目标是否为null
(请参阅该类的源代码),以及线程是否已完成其工作并“退出”。因此调用t2.run();
未能通过目标!=null
检查。对不起,我没有时间写答案:)。@Tom这听起来很划算。基本上,他对每个线程的run()
方法生成了两个调用。一个是异步和间接的(start()
),另一个是同步和直接的(run()
)。您可能希望在线程退出时将target
设置为null是一个实现细节,可能会在JVM实现中有所不同。还有另一个原因是t1.run()
没有问题。您演示了thread\run()
在线程启动后不执行任何操作,并允许运行到完成;但是t1.run()
从不调用thread#run()
。它调用OP的ThreadImpl#run()
方法,该方法没有相同的限制。@jameslarge,这是正确的。't1.run()'直接调用被重写的方法,而't2.run()'调用“原始”版本。感谢所有人,尤其是汤姆。@Slipknot不客气。如果这有助于您解决问题,请不要忘记。
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;
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;