跳槽不算频繁,但参加过不少面试(电话面试、face to face面试),面过大/小公司、互联网/传统软件公司,面糊过(眼高手低,缺乏实战经验,挂掉),也面过人,所幸未因失败而气馁,在此过程中不断查缺补漏,养成了踏实、追本溯源、持续改进的习惯,特此将自己经历过、构思过的一些面试题记录下来,如果答案有问题,欢迎拍砖讨论,希望能对找工作或者感兴趣的同学有所帮助,陆续整理中。

1. synchronized和reentrantlock异同

相同点

都实现了多线程同步和内存可见性语义

都是可重入锁

不同点

实现机制不同 synchronized通过java对象头锁标记和Monitor对象实现 reentrantlock通过CAS、ASQ(AbstractQueuedSynchronizer)和locksupport(用于阻塞和解除阻塞)实现 synchronized依赖jvm内存模型保证包含共享变量的多线程内存可见性 reentrantlock通过ASQ的volatile state保证包含共享变量的多线程内存可见性

使用方式不同 synchronized可以修饰实例方法(锁住实例对象)、静态方法(锁住类对象)、代码块(显示指定锁对象) reentrantlock显示调用trylock()/lock()方法,需要在finally块中释放锁

功能丰富程度不同 reentrantlock提供有限时间等候锁(设置过期时间)、可中断锁(lockInterruptibly)、condition(提供await、signal等方法)等丰富语义 reentrantlock提供公平锁和非公平锁实现 synchronized不可设置等待时间、不可被中断(interrupted)

2. concurrenthashmap为何读不用加锁

jdk1.7

1)HashEntry中的key、hash、next 均为final 型,只能表头插入、删除结点

2)HashEntry类的value域被声明为volatile型

3)不允许用null作为键和值,当读线程读到某个HashEntry的 value域的值为null时,便知道产生了冲突——发生了重排序现象(put设置新value对象的字节码指令重排序),需要加锁后重新读入这个value值

4)volatile变量count协调读写线程之间的内存可见性,写操作后修改count,读操作先读count,根据happen-before传递性原则写操作的修改读操作能够看到

jdk1.8

1)Node的val和next均为volatile型

2)tabAt和casTabAt对应的unsafe操作实现了volatile语义

3. ContextClassLoader(线程上下文类加载器)的作用

越过类加载器的双亲委派机制去加载类,如serviceloader实现

使用线程上下文类加载器加载类,要注意保证多个需要通信的线程间的类加载器应该是同一个,防止因为不同的类加载器导致类型转换异常(ClassCastException)

4. tomcat 类加载机制

不同应用使用不同的 webapp类加载器,实现应用隔离的效果,webapp类加载器下面是jsp类加载器

不同应用共享的jar包可以放到Shared类加载器/shared目录下

5. osgi类加载机制

osgi类加载模型是网状的,可以在模块(Bundle)间互相委托

osgi实现模块化热部署的关键是自定义类加载器机制的实现,每个Bundle都有一个自己的类加载器,当需要更换一个Bundle时,就把Bundle连同类加载器一起换掉以实现代码的热替换

当收到类加载请求时,osgi将按照下面的顺序进行类搜索:

1)将以java.*开头的类委派给父类加载器加载

2)否则,将委派列表名单(配置文件org.osgi.framework.bootdelegation中定义)内的类委派给父类加载器加载

3)否则,检查是否在Import-Package中声明,如果是,则委派给Export这个类的Bundle的类加载器加载

4)否则,检查是否在Require-Bundle中声明,如果是,则将类加载请求委托给required bundle的类加载器

5)否则,查找当前Bundle的ClassPath,使用自己的类加载器加载

6)否则,查找类是否在自己的Fragment Bundle中,如果在,则委派给Fragment Bundle的类加载器加载

7)否则,查找Dynamic Import-Package(Dynamic Import只有在真正用到此Package的时候才进行加载)的Bundle,委派给对应Bundle的类加载器加载

8)否则,类查找失败

6. 如何结束一个一直运行的线程

使用退出标志,这个flag变量要多线程可见

使用interrupt,结合isInterrupted()使用

7. threadlocal使用场景及问题

threadlocal并不能解决多线程共享变量的问题,同一个 threadlocal所包含的对象,在不同的thread中有不同的副本,互不干扰

用于存放线程上下文变量,方便同一线程对变量的前后多次读取,如事务、数据库connection连接,在web编程中使用的更多

问题: 注意线程池场景使用threadlocal,因为实际变量值存放在了thread的threadlocalmap类型变量中,如果该值没有remove,也没有先set的话,可能会得到以前的旧值

问题: 注意线程池场景下的内存泄露,虽然threadlocal的get/set会清除key(key为threadlocal的弱引用,value是强引用,导致value不释放)为null的entry,但是最好remove

8. 线程池从启动到工作的流程

刚创建时,里面没有线程

调用 execute() 添加任务时:

1)如果正在运行的线程数量小于核心参数corePoolSize,继续创建线程运行这个任务

2)否则,如果正在运行的线程数量大于或等于corePoolSize,将任务加入到阻塞队列中

3)否则,如果队列已满,同时正在运行的线程数量小于核心参数maximumPoolSize,继续创建线程运行这个任务

4)否则,如果队列已满,同时正在运行的线程数量大于或等于 maximumPoolSize,根据设置的拒绝策略处理

5)完成一个任务,继续取下一个任务处理

6)没有任务继续处理,线程被中断或者线程池被关闭时,线程退出执行,如果线程池被关闭,线程结束

7)否则,判断线程池正在运行的线程数量是否大于核心线程数,如果是,线程结束,否则线程阻塞。因此线程池任务全部执行完成后,继续留存的线程池大小为corePoolSize

9. 阻塞队列BlockingQueue take和poll区别

poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null

take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻塞直到BlockingQueue有新的对象被加入

10. 如何从FutureTask不阻塞获取结果

get(long timeout,TimeUnit unit),超时则返回

轮询,先通过isDone()判断是否结束,然后调用get()

11. blockingqueue如果存放了比较关键的数据,系统宕机该如何处理

开放性问题,欢迎讨论

将队列持久化,比较麻烦,需要将生产数据持久化到磁盘,持久化成功才返回,消费者线程从磁盘加载数据到内存阻塞队列中,维护消费offset,启动时,根据消费offset从磁盘加载数据

加入消息队列,保证消息不丢失,生成序列号,消费幂等,根据消费进程决定系统重启后的生产状态

12. NIO与传统I/O的区别

节约线程,NIO由原来的每个线程都需要阻塞读写变成了由单线程(即Selector)负责处理多个channel注册(register)的兴趣事件(SelectionKey)集合(底层借助操作系统提供的epoll()),netty bossgroup处理accept连接(没看明白为什么bossgroup设置多个thread的必要性),workergroup处理具体业务流程和数据读写

NIO提供非阻塞操作

传统I/O 以流的方式处理数据,而 NIO 以块的方式处理数据,NIO提供bytebuffer,分为堆内和堆外缓冲区,读写时均先放到该缓冲区中,然后由内核通过channel传输到对端,堆外缓冲区不走内核,提升了性能

13. list中存放可重复字符串,如何删除某个字符串

调用iterator相关方法删除

倒删,防止正序删除导致的数组重排,index跳过数组元素问题

14. 有哪些GC ROOTS(跟日常开发比较相关的是和此相关的内存泄露)

所有Java线程当前活跃的栈帧里指向GC堆里的对象的引用,因此用不到的对象及时置null,提升内存回收效率

静态变量引用的对象,因此减少静态变量特别是静态集合变量的大小,集合存放的对象覆写euqls()和hashcode(),防止持续增长

本地方法JNI引用的对象

方法区中的常量引用的对象,因此减少在长字符串上调用String.intern()

classloader加载的class对象,因此自定义classloader无效时及时置null并且注意类加载器加载对象之间的隔离

jvm里的一些静态数据结构里指向GC堆里的对象的引用

欢迎工作一到五年的Java工程师朋友们加入Java填坑之路:860113481

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代

一线互联网常见的14个Java面试题,你颤抖了吗程序员...相关推荐

  1. 一线互联网常见的14个Java面试题,你颤抖了吗程序员

    跳槽不算频繁,但参加过不少面试(电话面试.face to face面试),面过大/小公司.互联网/传统软件公司,面糊过(眼高手低,缺乏实战经验,挂掉),也面过人,所幸未因失败而气馁,在此过程中不断查缺 ...

  2. 精通C语言Java怎么样_作为一个优秀的程序员,真的需要精通C语言吗?

    从事嵌入式开发多年,使用C语言开发已经超过十个年头,除了C语言还用C++,java,python做过项目,程序员的优秀编程语言仅仅占据一部分,而且也不会只是针对C语言,现在很多的编程高手也不懂的C语言 ...

  3. java实现心形图案|桃心_程序员的浪漫--java打印心形图案

    原标题:程序员的浪漫--java打印心形图案 谁说程序员不能浪漫 单纯的心 双心 加些点缀 代码所用方程: 心:((0.05*x)^2 + (0.1*y)^2-1)^3-(0.05*x)^2 * (0 ...

  4. java只会用不知道原理6_程序员面试宝典之14道初级Java面试题分享

    程序员面试宝典之14道初级Java面试题分享 程序员面试宝典之14道初级Java面试题分享! 关于赢在面试的Java题系列基本收集整理完成了,所有题目都是经过精心挑选的,很基础又考验求职者的基本功,应 ...

  5. java双引号的转义字符_好程序员Java教程分享常见的转义字符

    原标题:好程序员Java教程分享常见的转义字符 好程序员Java教程分享常见的转义字符,在Java字符常量中,反斜杠(\)是一个特殊的字符,被称为转义字符,它的作用是用来转义后面一个字符.转义后的字符 ...

  6. “一线城市,年薪30万+,我却裸辞回老家”一个前程序员的 10 年职业思考

    作者 | 柚子 来源 | LinkedIn(ID:LinkedIn-China) 2020年一场疫情让全世界陷入困境,大量企业倒闭,被迫裁员,很多人失业. "996"." ...

  7. java安卓开发 快速入门_安卓程序员如何快速入门后端开发常识

    首先,对于安卓开发人员来说,学习一下后端开发知识是有必要的,一方面可以拓展自身的知识面,另一方面也可以推动自己走向全栈程序员发展路线,在云计算时代,全栈程序员的发展空间会更大一些. 相对来说,安卓程序 ...

  8. Java工程师成神之路:程序员的学习路线规划以及书籍推荐

    2019独角兽企业重金招聘Python工程师标准>>> 一.基础篇 面向对象 什么是面向对象 面向对象.面向过程 面向对象的三大基本特征和五大基本原则 平台无关性 Java如何实现的 ...

  9. java 数学公式解析框架有哪些_java程序员该如何进阶?这份java中高级核心知识全面解析请收好...

    <Java中高级核心知识全面解析>是整理收录GitHub50K+Star以上的高质量学习文档,前前后后花了近半个月的时间,终于整理而成.包含了Java基础.网络.Linux.数据结构与算法 ...

最新文章

  1. VMware 6.5开始,VMware vSphere ESXI只能通过浏览器访问
  2. 安裝 CentOS 7 後必做的七件事
  3. qt 雷达扫描障碍物_自动驾驶系统入门(五) - 激光雷达
  4. 使用jdbc连接mysql数据库代码示例
  5. 云+X案例展 | 传播类:九州云 SD-WAN 携手上海电信,助力政企客户网络重构换新颜...
  6. 初识Node.js之Node.js与java作为后台服务器的对比
  7. 账号密码数据库加密说明
  8. 5. Mac phpstorm 快捷键
  9. php如何只删去汉字,php如何删除字符串中的中文
  10. VC++运行库安装难题
  11. TVS管、稳压管、肖特基二极管
  12. 国家电网 计算机 《信息新技术》 整理
  13. Vue 项目(网站应用)接入QQ互联qq登录接口 汇总
  14. 【证明】欧拉公式(泰勒展开)
  15. 计算机运行但屏幕黑屏,电脑显示器黑屏,教您电脑主机运行正常显示器黑屏怎么办...
  16. ffmpeg提取mp4文件中的音频,保存为wav文件
  17. STM32开发必备知识篇:STM32的运行机制
  18. cpp map 获取所有 key_酪蛋白磷酸肽CPP:促进钙吸收它超强
  19. 如何把删除的文件复原?恢复数据其实也不难
  20. 家用电脑改造成服务器

热门文章

  1. 2017年云计算行业新动向盘点
  2. [转-SSRF]什么是SSRF
  3. 第2章 变量和基本类型 附3---底层const和顶层const
  4. python之高性能网络编程并发框架eventlet实例
  5. 比雷蛇0day更严重:通过虚拟赛睿外设即获取 Windows 管理员权限
  6. 网络间谍组织 SideCopy 攻击印度政府和军队组织
  7. “机智号”成功试飞火星,但它使用的开源软件安全吗?
  8. 一个价值$1.5万的 PS NOW 漏洞
  9. 下载量超1600万的热门开源 JavaScript 序列化包中被曝 RCE 漏洞
  10. Jenkins任务优先分配到原来的执行节点上