Java-初步认识-第十三章-第二种方式的细节

一. 讨论一下第二中方式中的一些细节问题

这里会产生一些疑问,Thread类有自己的线程方法(我估计是run方法),d也有自己的run方法。那么d传递到Thread中,那么t1既具备Thread类的run,又具备d的run,那它运行的是谁的?

通过刚才演示的来看,不传递运行的是Thread类自己的,传递后就是我指定的。这是为什么呢?

其实它内部的设计思想是这样的,源代码特别多,这里只是模拟一下重要部分。

常见的Thread类中应该具备截图中的四种方法,如果没有传递d对象,那么new的就是Thread()这个对象,那么它在调用run方法的时候,走的就是自己的run方法中的内容。如果你要是传递了d对象,那么走的就是Thread(Runable r),调用的还是Thread类中的run方法,因为start()方法启动的就是本类run方法。

可是调用这个run,为什么Demo类中的run方法运行了呢?其实特别简单,这里面持有了

通过截图可以发现,Thread类里面居然可以创建对象r,这个r就和成员变量一样使用?很奇怪。

解析:

创建多线程第一种方式,是采用的继承体系来完成的,比较好理解,这里不再赘述。

创建线程的第二种方式,是借助了runable接口的形式。通过自定义类实现接口,获得run()方法。现在最终要的是将获得的自定义类获得的run()和Thread类构上关系,使得Thread类的对象在调用start()方法时,运行的是自定义类中的run()方法,因为run()方法必须通过start()方法来启动。

(这里截图中的run()方法是为了覆盖Runnable类中的run方法,让自定义类中的封装代码块得以运行。)

这里Thread子类不存在了,而是Thread类直接构建自己类的对象。

创建的对象t在调用start()方法后,运行的是start()方法体中的run();而public void run();语句执行的是r.run();但是Thread类中是没有r的。

也就是说要进行一个判断,只有r不为空的时候,才能调用r对象的run()方法。如果为空,那就啥也不做。

所以必须要有实参传递的存在,如下图所示,也就是说,自定义类ThreadImpl类创建了本类对象i,(这个类是实现了runable接口,获得了run方法),将i对象传递到Thread类对象中,对其进行创建对象的构造初始化。接下来就是Thread类中的Thread(Runable r)初始化过程,也就是this.r=r。再接着执行的启动执行run方法时,就有了r.run();如果没有i对象的存在和传递,那么r.run()中的r就不存在。

这里是对创建线程第二种方式原理,进行地深入剖析。

这里我有两个疑惑:1. 实现接口的自定义类创建的对象i,传递到Thread类中,它的类型居然还是Runable。2. Thread类中private Runable r;这句也不太理解,这个接口类型的变量,也可以充当成员变量?

猜你喜欢

转载自blog.csdn.net/fighting_future/article/details/80277745