大部分面试时面试官会问,为什么开始一个线程时调用start方法而不是run方法呢?这里主要涉及到Thread里用到了模板设计模式。
public class test {
public final void print(){
System.out.println("##################");
messgae();
System.out.println("##################");
}
public void messgae(){}
public static void main (String arg[]) throws Exception{
test t=new test(){
@Override
public void messgae(){
System.out.println("我是执行体");
}
};
t.print();
}
}
类似这样的就是模板设计模式,程序结构由父类控制,执行体由子类来实现。上面的print方法对应于Thread类的start方法,而messgae对应于
Thread类的run方法,接下来我们查看Thread类的start方法和run方法
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
start方法代码很简单,但是核心的方法是这个 start0();但是这个start0是一个本地方法
private native void start0();
但是run方法什么时候被调用了呢,这里我们完全看不出,于是JDK文档的start方法上面有一句话说:
Causes this thread to begin execution; the Java Virtual Machine calls the
runcode> method of this thread.
也就是说在线程开始时,jVM会调用这个run,也就是本地方法start0会调用这个run方法,于是我们再看看run方法的
@Override
public void run() {
if (target != null) {
target.run();
}
}
我们发现这个run方法有个target,我们再找到这个target,原来target是
/* What will be run. */
private Runnable target;
所以Thread再这里判断是否有Runnable实现类,如果没有就是空的实现,
2.总结创建线程方式
如果你是继承Thread来创建线程,那么你可以直接重载run方法
如果你是用实现Runnable的接口,你只要实现Runnable接口的run方法,然后传入Thread来创建线程,然后Thread的run方法会调用Runnable接口的run方法。
总结:所以无论怎么样,我们都要是用Thread类来创建线程的,也就是说我们创建线程只有Thread类,而创建执行单元有多种方式,比如继承Thread类重载run方法或者实现Runnable接口的run方法。
原创来源:滴一盘技术