跟小白一起领悟Thread——如何开启一个线程(上)

校招面试回忆录:请说出在Java中如何开启一个线程?

上述两张图来自jdk1.8Thread类的注释,真有点八股文答案的意思了。。。。。 总结下来就是:

  • 要么继承Thread类并实现它的run方法
  • 要么实现Runnable接口,在构造Thread的时候当作参数传进去。

但是仔细思考发现Thread类本身是实现Runnable接口的,那么其实方法一本质也是方法二的变体;这时候有人就会说还有一种创建线程方式------Callable接口;确实是的,在提交线程池任务的时候,为了同时满足异步和获取结果,我们通常将任务包装成Callable丢给线程池,线程池底层使用的Thread。但是当我们仔细寻找Thread类中有没有Callable接口的蛛丝马迹,结果也是找不到的,原因也很简单,如下图所示:

实际上,我们给线程池提交的Callable接口被newTaskFor方法转换成了Ruunbale接口的子类RunnableFuture对象,根据做里氏替换原则,在构造Thread的时候是可以当作参数传进去的。 好像分析到这最终的答案也比较明确了,真相只有一个,实现Runnable接口。 但是,根据我自己的思考,我认为实现Runnable接口,好像并不是创建或者说开启一个线程的关键。因为实现runnable,继承Thread并创建对象也罢,这些行为都并不是发生在要创建的线程中,那么真正发生在创建的线程中的行为应该是执行了Runnable接口run方法的线程;那么触发运行执行了Runnable接口run方法的操作就是Thread的start方法,对该方法追根溯源会到一个jni方法:

也就是说,调用Thread的start方法会调用start0这个jni方法,从而与jvm层面实现的方法进行交互,jvm作为一款虚拟机提供了独立且完整的虚拟计算机环境,那么在Java语言层面的Thread也会映射到jvm的线程管理概念,然后jvm再去将jvm线程概念映射到操作系统内核线程上,这样才能实现真正的被操作系统调度从而获取cpu执行的条件。总的来讲,Java语言层面的Thread被称作用户态线程,jvm负责对该用户态线程与内核态线程进行映射,从而获取被调度的能力。所以我给出的答案是Java中如何开启一个线程是调用Thread对象的start方法,与jvm虚拟机进行交互,实现"注册"和"委托"映射到内核态线程,这里利用jstack来看下:

线程ID:#11=====>线程ID(JVM):tid=0x000000015d066000=====>本地线程ID:nid=0x5803,在这里java的Thread其实到内核态线程映射转换了两次。

也就是说,Runnable的run方法实现逻辑以及Callable的call方法实现逻辑(被封装为FutureTask类后,其实也是在run方法内调用call方法)其实更多的是定义了要执行的任务是什么,而不是创建一个新线程;

换个角度思考,线程池通过对线程的池化,不断的复用Thread,干完一个任务(Runnable)还是会干下一个任务(Runnable)的,不会说是来一个任务,就要创建一个新的线程去做;以下是线程池中线程的run方法调用的runWorker方法,不断的getTask并运行:

那为什么Thread不能直接接受Callable而是要包装成Runnable呢?从源码的注释可以得到一些信息,Thread和Runnable是since jdk1.0的,而Callable是由大神Doug Lea在jdk1.5提交的,在这个jdk版本,Doug Lea还提交了线程池系列的源码,也就是说Callable是线程池生态圈时期诞生的,领先于Thread和Runnable的发行时期,这里笔者大胆推断是更好管理,让Runnable成为定义任务的顶级接口,也有助于逻辑的实现。

面试官:你这回答的和我一分钟前搜的答案不太一样呀,还是回去等通知吧!

相关推荐
AAA修煤气灶刘哥6 分钟前
别再懵了!Spring、Spring Boot、Spring MVC 的区别,一篇讲透
后端·面试
ciku29 分钟前
Spring AI Starter和文档解读
java·人工智能·spring
柏油30 分钟前
MySQL 字符集 utf8 与 utf8mb4
数据库·后端·mysql
程序猿阿越39 分钟前
Kafka源码(三)发送消息-客户端
java·后端·源码阅读
javadaydayup40 分钟前
Apollo 凭什么能 “干掉” 本地配置?
spring boot·后端·spring
似水流年流不尽思念41 分钟前
Spring MVC 中的 DTO 对象的字段被 transient 修饰,可以被序列化吗?
后端·面试
武子康42 分钟前
大数据-70 Kafka 日志清理:删除、压缩及混合模式最佳实践
大数据·后端·kafka
whitepure44 分钟前
万字详解Java中的运算
java
故此2661 小时前
synchronized原理
后端