A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© nengYouDuoNiu 中级黑马   /  2016-7-26 22:32  /  398 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

前言:
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()



0 个回复

您需要登录后才可以回帖 登录 | 加入黑马