几道让你拿offer的Java面试知识点,腾讯T2大牛亲自教你

    System.out.println(localLong.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue())));



    // ... 最后一句在这里漏掉了,大家应该可以推断出来

}

}




我使用的反编译工具是`jd-gui`,如果还没有试过反编译的同学可以下载来玩玩:



*   [https://github.com/java-decompiler/jd-gui/releases](https://gitee.com/vip204888/java-p7)



二、Synchronize锁优化手段有哪些

=====================



多线程文章回顾:



*   [ThreadLocal就是这么简单](https://gitee.com/vip204888/java-p7)

*   [多线程三分钟就可以入个门了!](https://gitee.com/vip204888/java-p7)

*   [Thread源码剖析](https://gitee.com/vip204888/java-p7)

*   [多线程基础必要知识点!看了学习多线程事半功倍](https://gitee.com/vip204888/java-p7)

*   [Java锁机制了解一下](https://gitee.com/vip204888/java-p7)

*   [AQS简简单单过一遍](https://gitee.com/vip204888/java-p7)

*   [Lock锁子类了解一下](https://gitee.com/vip204888/java-p7)

*   [线程池你真不来了解一下吗?](https://gitee.com/vip204888/java-p7)

*   [多线程之死锁就是这么简单](https://gitee.com/vip204888/java-p7)

*   [Java多线程打辅助的三个小伙子](https://gitee.com/vip204888/java-p7)



之前在写多线程文章的时候,简单说了一下synchronized锁在jdk1.6以后会有各种的优化:适应自旋锁,锁消除,锁粗化,轻量级锁,偏向锁。



![](https://user-gold-cdn.xitu.io/2018/8/2/164f805aac3f5b04?w=1297&h=696&f=png&s=61882)



本以为这些优化是非常难以理解的东西,其实不然~~~简单了解一下还是很好理解的。



2.1适应自旋锁

--------



锁竞争是kernal mode下的,会经过user mode(用户态)到kernal mode(内核态) 的**切换**,是比较花时间的。



**自旋锁**出现的原因是人们发现大多数时候**锁的占用只会持续很短的时间**,甚至低于切换到kernal mode所花的时间,所以在进入kernal mode前让线程等待有限的时间,如果在此时间内能够获取到锁就**避免了很多无谓的时间**,若不能则再进入kernal mode竞争锁。



在JDK 1.6中引入了自适应的自旋锁,说明**自旋的时间不固定,要不要自旋变得越来越聪明**。



自旋锁在JDK1.4.2中就已经引入,只不过默认是关闭的,可以使用`-XX:+UseSpinning`参数来开启,在JDK1.6中就已经改为**默认**开启了。



参考资料:



*   自旋锁和使线程休眠的非自旋锁各有什么适用场景?[https://www.zhihu.com/question/38857029/answer/78480263](https://gitee.com/vip204888/java-p7)



2.2锁消除

------



如果JVM明显检测到某段代码是**线程安全**的(言外之意:无锁也是安全的),JVM会安全地原有的锁消除掉!



比如说:



public void vectorTest(){

    Vector<String> vector = new Vector<String>();

    for(int i = 0 ; i < 10 ; i++){

        vector.add(i + "");

    }



    System.out.println(vector);

}



Vector是默认加锁的,但JVM如果发现vector变量仅仅在`vectorTest()`方法中使用,那该vector是线程安全的。JVM会把vector内部加的锁去除,这个优化就叫做:锁消除。



2.3锁粗化

------



默认情况下,总是推荐将**同步块的作用范围限制得尽量小**。



但是如果一系列的连续操作都对**同一个对象反复加锁和解锁**,甚至加锁操作是出现在循环体中的,频繁地进行互斥同步操作也会导致**不必要的性能损耗**。



JVM会将加锁的范围**扩展**(粗化),这就叫做锁粗化。



2.4轻量级锁

-------



轻量级锁能提升程序同步性能的依据是**“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”**,这是一个经验数据。



*   如果没有竞争,轻量级锁使用**CAS操作避免了使用互斥量的开销**

*   但如果存在锁竞争,除了互斥量的开销外,还额外发生了CAS操作,因此在有竞争的情况下,轻量级锁会比传统的重量级锁更慢。



简单来说:如果发现同步周期内都是**不存在竞争**,JVM会使用**CAS操作来替代操作系统互斥量**。这个优化就被叫做轻量级锁。



2.5偏向锁

------



偏向锁就是在**无竞争的情况下把整个同步都消除掉,连CAS操作都不做了**!



> 偏向锁可以提高**带有同步但无竞争的程序性能**。它同样是一个带有效益权衡(Trade Off)性质的优化,也就是说,它并不一定总是对程序运行有利,如果程序中大多数的锁总是被多个不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下,有时候使用参数`-XX:-UseBiasedLocking`来禁止偏向锁优化反而可以提升性能。



2.6简单总结各种锁优化

------------



*   自适应偏向锁:自旋时间不固定

*   锁消除:如果发现代码是线程安全的,将锁去掉

*   锁粗化:加锁范围过小(重复加锁),将加锁的范围扩展

*   轻量级锁:在无竞争的情况下**使用CAS操作去消除同步使用的互斥量**

*   偏向锁:在无竞争环境下,把整个同步都消除,CAS也不做。



参考资料:



*   [https://blog.csdn.net/chenssy/article/details/54883355](https://gitee.com/vip204888/java-p7)



三、TCP粘包,拆包

==========



这是在看wangjingxin大佬面经的时候看到的面试题,之前对TCP粘包,拆包没什么概念,于是就简单去了解一下。



3.1什么是拆包粘包?为什么会出现?

------------------



在进行Java NIO学习时,**可能**会发现:如果客户端**连续不断**的向服务端发送数据包时,服务端接收的数据会出现两个数据包**粘在**一起的情况。



TCP的首部格式:



![](https://img-blog.csdnimg.cn/img_convert/5adaab4d74853c6e99d62b5fbda4d774.png)



*   TCP是**基于字节流的**,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,**没有边界**;

*   从TCP的帧结构也可以看出,在TCP的首部**没有表示数据长度的字段**



基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。



**一个数据包中包含了发送端发送的两个数据包的信息**,这种现象即为粘包



![](https://img-blog.csdnimg.cn/img_convert/76fea7cdc5382c61d5e0312be773aef5.png)



接收端收到了两个数据包,但是这两个数据包**要么是不完整的,要么就是多出来一块**,这种情况即发生了拆包和粘包



![](https://img-blog.csdnimg.cn/img_convert/d991d137935d177c4efbc1162b877847.png)



拆包和粘包的问题导致**接收端在处理的**时候会非常困难(因为无法区分一个**完整的**数据包)



3.2解决拆包和粘包

----------



分包机制一般有两个**通用**的解决方法:



*   1,特殊字符控制

*   2,在包头首都添加数据包的长度



如果使用netty的话,就有专门的编码器和解码器解决拆包和粘包问题了。



> tips:**UDP没有粘包问题**,但是有丢包和乱序。不完整的包是不会有的,收到的都是完全正确的包。传送的数据单位协议是UDP报文或用户数据报,发送的时候既不合并,也不拆分。



参考资料



*   [https://blog.csdn.net/scythe666/article/details/51996268](https://gitee.com/vip204888/java-p7)\--->TCP粘包,拆包及解决方法

*   [http://www.ideawu.net/blog/archives/993.html](https://gitee.com/vip204888/java-p7)\--->关于TCP粘包和拆包的终极解答



四、select、poll、epoll简单区别

=======================



NIO回顾:



*   [JDK10都发布了,nio你了解多少?](https://gitee.com/vip204888/java-p7)



在Linux下它是这样子实现I/O复用模型的:



调用`select/poll/epoll`其中一个函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。



这几个函数是有些区别的,可能有的面试官会问到这三个函数究竟有什么区别:



区别如下图:



![](https://img-blog.csdnimg.cn/img_convert/a503a88fc2a5e9b8ccd3fd02a6297b1d.png)



两句话总结:



*   `select和poll`都需要轮询每个文件描述符,`epoll`基于事件驱动,不用轮询

*   `select和poll`每次都需要拷贝文件描述符,`epoll`不用

*   `select`最大连接数受限,`epoll和poll`最大连接数不受限



> tips:epoll在内核中的实现,用红黑树管理事件块



4.1通俗例子

-------



现在3y在公司里边实习,写完的代码需要给测试测一遍。



`select/poll`情况:



*   开发在写代码,此时测试**挨个问**所有开发者,你写好程序了没有?要测试吗?



`epoll`情况:



*   开发写完代码了,告诉测试:“我写好代码了,你去测测,功能是XXX”。于是测试高高兴兴去找bug了。



其他通俗描述\[1\]:



> 一个酒吧服务员(一个线程),前面趴了一群醉汉,突然一个吼一声“倒酒”(事件),你小跑过去给他倒一杯,然后随他去吧,突然又一个要倒酒,你又过去倒上,就这样一个服务员服务好多人,有时没人喝酒,服务员处于空闲状态,可以干点别的玩玩手机。至于epoll与select,poll的区别在于后两者的场景中醉汉不说话,你要挨个问要不要酒,没时间玩手机了。io多路复用大概就是指这几个醉汉共用一个服务员。



来源:



*   [https://www.zhihu.com/question/32163005/answer/55687802](https://gitee.com/vip204888/java-p7)




# 惊喜

最后还准备了一套上面资料对应的面试题(有答案哦)和面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

![image.png](https://img-blog.csdnimg.cn/img_convert/a2f6f9cda63f0e1b601d8a25895dd31a.png)


![image.png](https://img-blog.csdnimg.cn/img_convert/c3838a44e11db29168828428e1106450.png)

人,有时没人喝酒,服务员处于空闲状态,可以干点别的玩玩手机。至于epoll与select,poll的区别在于后两者的场景中醉汉不说话,你要挨个问要不要酒,没时间玩手机了。io多路复用大概就是指这几个醉汉共用一个服务员。



来源:



*   [https://www.zhihu.com/question/32163005/answer/55687802](https://gitee.com/vip204888/java-p7)




# 惊喜

最后还准备了一套上面资料对应的面试题(有答案哦)和面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)

[外链图片转存中...(img-NxYRsQqs-1628398129983)]


[外链图片转存中...(img-jRV035oV-1628398129984)]

**[资料获取方式:戳这里免费领取](https://gitee.com/vip204888/java-p7)**
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值