当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单
当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单
这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家。 点赞再看,养成习惯~ 微信搜索【武哥聊编程】,关注这个 Java 菜鸟。
昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的问题:你说一说 Java 创建线程都有哪些方式?
这哥们心中窃喜,这个老生常谈的问题早已背的滚瓜烂熟,于是很流利的说了出来。
Java 创建线程有两种方式:
继承Thread类,并重写run()方法
实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread
面试官:(拿出一张白纸)那你把这两种方式写一下吧!
小哥:(这有何难!)好~
public static void main(String[] args) {
// 第一种 MyThread myThread = new MyThread(); myThread.start(); // 第二种 new Thread(() -> System.out.println("自己实现的run-2")).start();
}
public static class MyThread extends Thread {
@Override public void run() { System.out.println("自己实现的run-1"); }
}
面试官:嗯,那除了这两种,还有其他创建线程的方法吗?
这些简单的问题难不倒这哥们,于是他想到了 Java5 之后的Executors,Executors工具类可以用来创建线程池。
小哥:Executors工具类是用来创建线程池的,这个线程池可以指定线程个数,也可以不指定,也可以指定定时器的线程池,它有如下常用的方法:
newFixedThreadPool(int nThreads):创建固定数量的线程池 newCachedThreadPool():创建缓存线程池 newSingleThreadExecutor():创建单个线程 newScheduledThreadPool(int corePoolSize):创建定时器线程池
面试官:嗯,OK,咱们还是针对你刚刚写的代码,我再问你个问题。
此时这哥们有种不祥的预感,是不是自己代码写的有点问题?或者要问我底层实现?
面试官:你写的两种创建线程的方式,都涉及到了run()方法,你了解过Thread里的run()方法具体是怎么实现的吗?
果然问到了源码了,这哥们之前看了点,所以不是很慌,回忆了一下,向面试官道来。
小哥:emm……Thread 中的run()方法里东西很少,就一个 if 判断:
@Override
public void run() {
if (target != null) { target.run(); }
}
有个target对象,会去判断该变量是否为空,非空的时候,去执行target对象中的run()方法,否则啥也不干。而这个target对象,就是我们说的Runnable:
/ What will be run. /
private Runnable target;
面试官:嗯,那这个Runnable类你了解过吗? 小哥:了解过,这个Runnable类很简单,就一个抽象方法:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
这个抽象方法也是run()!如果我们使用Runnable接口,就需要实现这个run()方法。由于这个Runnable类上面标了@FunctionalInterface注解,所以可以使用函数式编程。
那小哥接着说:(突然自信起来了)所以这就对应了刚才说的两种创建线程的方式,假如我用第一种方式:继承了Thread类,然后重写了run()方法,那么它就不会去执行上面这个默认的run()方法了(即不会去判断target),会执行我重写的run()方法逻辑。
假如我是用的第二种方式:实现Runnable接口的方式,那么它会执行默认的run()方法,然后判断target不为空,再去执行我在Runnable接口中实现的run()方法。
面试官:OK,可以,我再问你个问题。
小哥:(暗自窃喜)
面试官:那如果我既继承了Thread类,同时我又实现了Runnable接口,比如这样,最后会打印什么信息出来呢?
面试官边说边拿起刚刚这小哥写的代码,对它进行了简单的修改:
public static void main(String[] args) {
new Thread(() -> System.out.println("runnable run")) { @Override public void run() { System.out.println("Thread run"); } }.start();
}
这小哥,突然有点懵,好像从来没想过这个问题,一时没有什么思路,于是回答了个:会打印 “Thread run” 吧……
面试官:答案是对的,但是为什么呢?
这小哥一时没想到原因,于是面试官让他回去可以思考思考,就继续下一个问题了。
亲爱的读者朋友,你们知道为什么吗?你们可以先思考一下。
其实这个答案很简单,我们来分析一下代码便知:其实是 new 了一个对象(子对象)继承了Thread对象(父对象),在子对象里重写了父类的run()方法;然后父对象里面扔了个Runnable进去,父对象中的run()方法就是最初那个带有 if 判断的run()方法。
好了,现在执行start()后,肯定先在子类中找run()方法,找到了,父类的run()方法自然就被干掉了,所以会打印出:Thread run。
如果我们现在假设子类中没有重写run()方法,那么必然要去父类找run()方法,父类的run()方法中就得判断是否有Runnable传进来,现在有一个,所以执行Runnable中的run()方法,那么就会打印:Runnable run 出来。
说白了,就是问了个 Java 语言本身的父子继承关系,会优先执行子类重写的方法而已,只是借这个场景,换了个提问的方式,面试者可能一时没反应过来,有点懵也是正常的,如果直接问,傻子都能回答的出来。
后记:通过这道简单的面试题,帮大家分析了一下在创建线程过程中的源码,可以看出来,面试过程中,面试官更加看重一些原理性的东西,而不是背一下方式就行了。同时也能看的出,面试大厂,需要做好充分的准备。另外,在面试的时候要冷静,可能有些问题并没有太难,回答不出来只是当时太紧张造成的。
这篇文章就写到这,最后祝大家都能面试成功。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
为什么我建议每个开发人员都需要学Python?
为什么我建议每个开发人员都需要学Python? 世界上只有几种编程语言提供多种功能。 在当今世界,开发人员必须能去构建各种类型的应用程序,所以多学习一种多功能开发语言是有必要的。 虽说php是世界上最好的语言,但这也不妨碍Python成为通用编程开发语言,它可以让开发人员构建各种类型的应用程序。 Web解决方案Python被认为是Web开发人员的首选语言之一。 因为有着许多由Python设计和支持的互联网巨头背书,如谷歌、YouTube、Netflix、Instagram、Dropbox、雅虎、Reddit、Spotify等等。Python为它们构建服务器端应用程序。因此,作为一名Web开发人员,学习并掌握它将可能对你未来的工作带来一些帮助。 Python还拥有了很多很棒的库,它们包括了例如:JSON、HTML、XML、beautifulSoup、Feedparser、电子邮件处理、Request等。同时Python还有一些很好用的框架,例如:Django,Pyramid,Flask,Tornado,web2py,CherryPy,Falcon等。 2.数据科学在当下的世界里,数据成为...
- 下一篇
SpringBoot整合Springfox-Swagger2
SpringBoot整合Springfox-Swagger2 前言 不管Spring Boot整合还是SpringMVC整合Swagger都基本类似,重点就在于配置Swagger,它的精髓所在就在于配置。 @[toc] 1、Swagger简介目前互联网时代前后端分离已成趋势,前后端混在一起,前端或者后端无法做到“及时协商,尽早解决”,最终导致问题集中爆发。解决方案就是前后端通过API进行交互达到相对独立且松耦合。Swagger就是这样的一个API框架,Swagger支持多种语言 如:Java,PHP等,它号称是世界上最流行的API框架! 2、整合前可能遇到的问题1、 导入好依赖jar包之后,使用注解说找不到之类的问题,如遇到,请参考:所有Intellij IDEA Cannot Resolve Symbol XXX问题的解决方法汇总 2、 版本问题,SpringBoot的版本很多,被集成的框架版本也很多,可能版本高一点或者低一点就可能出现各种bug,这是集成其他框架的通病,这里得注意一下。如果运行出现一些什么bug,如果对SpringBoot底层原理不是很了解的可以先百度谷歌一下,找不...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作