了解Java线程的start方法如何回调run方法
来源:互联网 发布:何晓飞 滴滴辞职 知乎 编辑:程序博客网 时间:2024/05/22 12:42
面试中可能会被问到为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法?
Java 创建线程的方法
实际上,创建线程最重要的是提供线程函数(回调函数),该函数作为新创建线程的入口函数,实现自己想要的功能。Java 提供了两种方法来创建一个线程:
继承 Thread 类
- 1
- 2
- 3
- 4
- 5
实现该继承类的 run 方法,然后就可以创建这个子类的对象,调用 start 方法即可创建一个新的线程:
- 1
- 2
实现 Runnable 接口
- 1
- 2
- 3
- 4
- 5
实现 Runnable 接口的类的对象可以作为一个参数传递到创建的 Thread 对象中,同样调用 Thread#start 方法就可以在一个新的线程中运行 run 方法中的代码了。
- 1
- 2
可以看到,不管是用哪种方法,实际上都是要实现一个 run 方法的。 该方法本质是上一个回调方法。由 start 方法新创建的线程会调用这个方法从而执行需要的代码。 从后面可以看到,run 方法并不是真正的线程函数,只是被线程函数调用的一个 Java 方法而已,和其他的 Java 方法没有什么本质的不同。
Java 线程的实现
从概念上来说,一个 Java 线程的创建根本上就对应了一个本地线程(native thread)的创建,两者是一一对应的。 问题是,本地线程执行的应该是本地代码,而 Java 线程提供的线程函数是 Java 方法,编译出的是 Java 字节码,所以可以想象的是, Java 线程其实提供了一个统一的线程函数,该线程函数通过 Java 虚拟机调用 Java 线程方法 , 这是通过 Java 本地方法调用来实现的。
以下是 Thread#start 方法的示例:
- 1
- 2
- 3
- 4
- 5
可以看到它实际上调用了本地方法 start0, 该方法的声明如下:
- 1
Thread 类有个 registerNatives 本地方法,该方法主要的作用就是注册一些本地方法供 Thread 类使用,如 start0(),stop0() 等等,可以说,所有操作本地线程的本地方法都是由它注册的 . 这个方法放在一个 static 语句块中,这就表明,当该类被加载到 JVM 中的时候,它就会被调用,进而注册相应的本地方法。
- 1
- 2
- 3
- 4
本地方法 registerNatives 是定义在 Thread.c 文件中的。Thread.c 是个很小的文件,定义了各个操作系统平台都要用到的关于线程的公用数据和操作,如代码清单 1 所示。
清单1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
到此,可以容易的看出 Java 线程调用 start 的方法,实际上会调用到 JVM_StartThread 方法,那这个方法又是怎样的逻辑呢。实际上,我们需要的是(或者说 Java 表现行为)该方法最终要调用 Java 线程的 run 方法,事实的确如此。 在 jvm.cpp 中,有如下代码段:
- 1
- 2
- 3
- 4
**这里JVM_ENTRY是一个宏,用来定义**JVM_StartThread 函数,可以看到函数内创建了真正的平台相关的本地线程,其线程函数是 thread_entry,如清单 2 所示。
清单2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
可以看到调用了 vmSymbolHandles::run_method_name 方法,这是在 vmSymbols.hpp 用宏定义的:
- 1
- 2
- 3
- 4
- 5
至于 run_method_name 是如何声明定义的,因为涉及到很繁琐的代码细节,本文不做赘述。感兴趣的读者可以自行查看 JVM 的源代码。
图. Java 线程创建调用关系图
start() 创建新进程
run() 没有
- 了解java线程的start方法如何回调run方法
- 了解Java线程的start方法如何回调run方法
- 了解Java线程的start方法如何回调run方法
- 了解Java线程的start方法如何回调run方法
- 了解Java线程的start方法如何回调run方法
- Java线程的start方法如何回调run方法
- java 线程 start 方法 跟 run 方法的区别
- 线程的run方法与start方法
- java 线程的run和start方法的不同
- Java 线程启动 run() 还是start() 方法
- JAVA线程中的run 和start方法
- Java线程中run和start方法
- Java线程中run和start方法的区别
- Java线程中run和start方法的区别
- Java线程中run和start方法的区别
- Java线程中run和start方法的区别
- Java线程中run和start方法的区别
- Java线程中run和start方法的区别
- java web项目中集成ueditor在线编辑器以及如何运用在线编辑器向后台传递数据
- SoLFM_learning
- GCD
- C++ 调试帮助简介
- 1008. 数组元素循环右移问题 (20)
- 了解Java线程的start方法如何回调run方法
- Python3发送邮件(三)(附件)(qq)
- Origin绘图后导出图片的方法
- Django通过HttpResponse如何返回用户头像
- py 正则表达式
- 创建和使用动态链接库
- HashMap的长度为什么要是2的n次方
- Android最新打包方式-支持V2
- 命令行选项