• 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;这句也不太理解,这个接口类型的变量,也可以充当成员变量?

  • 相关阅读:
    istio-流量管理-基于不同版本访问规则控制
    k8s安装istio
    策略模式
    递归思想
    Java Lambda 表达式
    redis实现分布式锁
    MySQL 的优化方案总结
    linux下查看某一端口被哪个进程占用
    组合模式
    桥接模式
  • 原文地址:https://www.cnblogs.com/wsw-bk/p/8023624.html
Copyright © 2020-2023  润新知