好的,我知道创建新线程并在Java中运行它的两种标准方法:
在类中实现Runnable
,定义run()
方法,并将类的实例传递给新的Thread
。当调用线程实例上的start()
方法时,将调用类实例的run方法。
让类派生自Thread
,因此它可以覆盖方法run()
,然后在调用新实例的start()
方法时,将调用路由到覆盖方法
在这两种方法中,基本上都会创建一个新的Thread
对象并调用其start方法。但是,在第二种方法中,调用的机制被路由到用户定义的run()
方法非常清楚,(这是一个简单的运行时多态性),我不明白如何调用{{ Thread对象上的方法被路由到实现start()
接口的类的run()
方法。 Runnable
类是否具有首先检查的类型Thread
的私有字段,如果已设置,则调用run方法(如果设置为对象)?这将是一个奇怪的机制IMO。
线程上对Runnable
的调用如何被路由到类的实现的start()
接口的run方法,该类的对象在构造线程时作为参数传递?
答案 0 :(得分:7)
Thread
保留对Runnable
实例的引用,并在run
的基本实现中调用它。
您可以在来源中看到这一点:
// passed into the constructor and set in the init() method
private Runnable target;
...
// called from native thread code after start() is called
public void run() {
if (target != null) {
target.run();
}
}
答案 1 :(得分:2)
虽然您可以查看实际的源代码,但猜测它会是:
public class MyThread implements Runnable {
private Runnable r;
public MyThread() {
}
public MyThread(Runnable r) {
this.r = r;
}
public void start() {
//magic to launch a new thread
run(); // the above magic would probably call run(), rather than
// call it directly here though.
}
public void run() {
if(r != null)
r.run();
}
}
简而言之,如果扩展MyThread并覆盖run(),则会调用run()方法。如果您传递了一个Runnable,MyThread的run()方法将委托给该Runnable的run()方法。
答案 2 :(得分:1)
在这两种情况下都必须有具体的Thread类。在第一种情况下(实现Runnable),使实现它的类能够“成为”一个线程。您仍然必须将您的类作为参数传递给Thread类的构造函数。而那不是第二种情况下扩展线程类的场景。
调用start()方法时,无法保证立即调用run()方法。调用start()方法可以告诉线程已准备好运行。此后它可以进入任何状态,具体取决于Thread pooler。
仅供参考:class Thread implements Runnable
答案 3 :(得分:1)
您刚刚检查了JDK中包含的Thread.java
的来源:
public void run() {
if (target != null) {
target.run();
}
}
目标是:
private Runnable target;
但我认为你正在寻找的真正答案是关于线程如何真正起作用的细节。不幸的是,这在本地图书馆中被抽象出来了。试着深入了解线程的工作原理。
答案 4 :(得分:1)
答案尚未探讨的一件事是事情如何从start()
传递到run()
,同时既简单又复杂。
简单来说,start()
方法调用OpenJDK实现中的本机方法(start0
),为新堆栈分配一些内存,并要求操作系统将该空间作为堆栈运行并使用普通的C ++函数(OpenJDK实现中的thread_entry
)作为实现函数。该函数反过来将thunk返回到Java以调用Thread对象上的run()
方法。在POSIX系统或Windows中执行本机线程的任何人都应该熟悉低级别的模式(要求操作系统在堆栈上启动新线程并使用函数)。
细节使得它变得更加复杂,需要处理所有错误处理和模糊的边缘情况。如果您感到好奇,请阅读OpenJDK来源,特别关注Thread.java
中的JVM_StartThread
,jvm.cpp
中的JavaThread
以及thread.cpp
中的thread.hpp
课程和{{1}}。希望这个答案能为您提供足够的细节,让您找到自己的方式......