前言:
MyRunnable是实现了Runnable接口,并且重写了Runnable接口的run方法。
Thread t = new Thread(new MyRunnable());
t.start();
----------------我是一道华丽的分割线,原创,不喜勿喷----------------------------
提问2:
为什么在Thread的构造方法中传入Runnable接口的子类对象MyRunnable,然后
调用Thread子类对象t的start方法,系统自动调用的T不是hread方法中run方法,而是MyRunnable的run方法?
源码简写:
[Java] 纯文本查看 复制代码 class Thread {
[b] ⑥[/b]private Runnable target;
//这里的target是我们传入的Runnable接口的子类对象MyRunnable
public Thread(Runnable target, String name) {
[backcolor=red] ①[/backcolor]init(null, target, name, 0);
}
[backcolor=red] ②[/backcolor]private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
[backcolor=red] ③[/backcolor]init(g, target, name, stackSize, null);
}
[backcolor=red] ④[/backcolor]private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
if (security != null) {
g = security.getThreadGroup();
}
if (g == null) {
g = parent.getThreadGroup();
}
}
g.checkAccess();
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
[backcolor=red] ⑤[/backcolor]this.target = target;
setPriority(priority);
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
tid = nextThreadID();
}
[backcolor=red] ⑦[/backcolor]public void run() {
if (target != null) {
target.run();
}
}
}
解答2:从构造函数开始分析:以target为线索,①调用了②,②调用了③,③调用了④,在④中找到⑤,从⑤中找到⑥
得到一个结论,target是Thread类的一个成员变量,类型为Runnable.
接下来,我们查找run方法,发现真正调用run方法的其实是成变量的target。
//总结:
其实new Runnable()这个Runnable接口的子类对象,赋值为Thread类中的成员变量target,这个时候,调用run()方法
其实就是多态的原理。编译看左边,运行看右边,所以最终执行的还是Runnable接口的子类对象run()
|