Java后台面试 常见问题
从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗offer。我找的是java后台开发,把常见的问题分享给大家,有一些是自己的总结,有一些是网上借鉴的内容。希望能帮助到各位。预祝各位同学拿到自己心仪的offer!
Nginx负载均衡
轮询、轮询是默认的,每一个请求按顺序逐一分配到不同的后端服务器,如果后端服务器down掉了,则能自动剔除
ip_hash、个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。
weight、weight是设置权重,用于后端服务器性能不均的情况,访问比率约等于权重之比
fair(第三方)、这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持fair的,如果需要使用这种调度算法,必须下载Nginx的upstream_fair模块。
url_hash(第三方)此方法按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,可以进一步提高后端缓存服务器的效率。Nginx本身是不支持url_hash的,如果需要使用这种调度算法,必须安装Nginx 的hash软件包。
代理的概念
正向代理,也就是传说中的代理, 简单的说,我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的网站,于是我先连上代理服务器,告诉他我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。从网站的角度,只在代理服务器来取内容的时候有一次记录,有时候并不知道是用户的请求,也隐藏了用户的资料,这取决于代理告不告诉网站。
反向代理: 结论就是,反向代理正好相反,对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置。客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向代理将判断向何处(原始服务器)转交请求,并将获得的内容返回给客户端,就像这些内容原本就是它自己的一样。
Volatile的特征:
A、原子性 :对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。
B、可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
Volatile的内存语义:
当写一个volatile变量时,JMM会把线程对应的本地内存中的共享变量值刷新到主内存。
当读一个volatile变量时,JMM会把线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量。
Volatile的重排序
1、当第二个操作为volatile写操做时,不管第一个操作是什么(普通读写或者volatile读写),都不能进行重排序。这个规则确保volatile写之前的所有操作都不会被重排序到volatile之后;
2、当第一个操作为volatile读操作时,不管第二个操作是什么,都不能进行重排序。这个规则确保volatile读之后的所有操作都不会被重排序到volatile之前;
3、当第一个操作是volatile写操作时,第二个操作是volatile读操作,不能进行重排序。
这个规则和前面两个规则一起构成了:两个volatile变量操作不能够进行重排序;
除以上三种情况以外可以进行重排序。
比如:
1、第一个操作是普通变量读/写,第二个是volatile变量的读;
2、第一个操作是volatile变量的写,第二个是普通变量的读/写;
内存屏障/内存栅栏
内存屏障(Memory Barrier,或有时叫做内存栅栏,Memory Fence)是一种CPU指令,用于控制特定条件下的重排序和内存可见性问题。Java编译器也会根据内存屏障的规则禁止重排序。(也就是让一个CPU处理单元中的内存状态对其它处理单元可见的一项技术。)
内存屏障可以被分为以下几种类型:
LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。
在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。
内存屏障阻碍了CPU采用优化技术来降低内存操作延迟,必须考虑因此带来的性能损失。为了达到最佳性能,最好是把要解决的问题模块化,这样处理器可以按单元执行任务,然后在任务单元的边界放上所有需要的内存屏障。采用这个方法可以让处理器不受限的执行一个任务单元。合理的内存屏障组合还有一个好处是:缓冲区在第一次被刷后开销会减少,因为再填充改缓冲区不需要额外工作了。
happens-before原则
如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。
Java是如何实现跨平台的?
跨平台是怎样实现的呢?这就要谈及Java虚拟机(JavaVirtual Machine,简称 JVM)。
JVM也是一个软件,不同的平台有不同的版本。我们编写的Java源码,编译后会生成一种 .class 文件,称为字节码文件。Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码然后运行。也就是说,只要在不同平台上安装对应的JVM,就可以运行字节码文件,运行我们编写的Java程序。
而这个过程中,我们编写的Java程序没有做任何改变,仅仅是通过JVM这一”中间层“,就能在不同平台上运行,真正实现了”一次编译,到处运行“的目的。
JVM是一个”桥梁“,是一个”中间件“,是实现跨平台的关键,Java代码首先被编译成字节码文件,再由JVM将字节码文件翻译成机器语言,从而达到运行Java程序的目的。
注意:编译的结果不是生成机器码,而是生成字节码,字节码不能直接运行,必须通过JVM翻译成机器码才能运行。不同平台下编译生成的字节码是一样的,但是由JVM翻译成的机器码却不一样。
所以,运行Java程序必须有JVM的支持,因为编译的结果不是机器码,必须要经过JVM的再次翻译才能执行。即使你将Java程序打包成可执行文件(例如 .exe),仍然需要JVM的支持。
注意:跨平台的是Java程序,不是JVM。JVM是用C/C++开发的,是编译后的机器码,不能跨平台,不同平台下需要安装不同版本的JVM。
垃圾搜集器
- 按照线程数量来分:
- 串行 串行垃圾回收器一次只使用一个线程进行垃圾回收
- 并行 并行垃圾回收器一次将开启多个线程同时进行垃圾回收。
- 按照工作模式来分:
- 并发 并发式垃圾回收器与应用程序线程交替工作,以尽可能减少应用程序的停顿时间
- 独占 一旦运行,就停止应用程序中的其他所有线程,直到垃圾回收过程完全结束
- 按照碎片处理方式:
- 压缩式 压缩式垃圾回收器会在回收完成后,对存活对象进行压缩整消除回收后的碎片;
- 非压缩式 非压缩式的垃圾回收器不进行这步操作。
- 按工作的内存区间 可分为新生代垃圾回收器和老年代垃圾回收器
新生代串行收集器 serial 它仅仅使用单线程进行垃圾回收;第二,它独占式的垃圾回收。使用复制算法。
老年代串行收集器 serial old 年代串行收集器使用的是标记-压缩算法。和新生代串行收集器一样,它也是一个串行的、独占式的垃圾回收器
并行收集器 parnew 并行收集器是工作在新生代的垃圾收集器,它只简单地将串行回收器多线程化。它的回收策略、算法以及参数和串行回收器一样 并行回收器也是独占式的回收器,在收集过程中,应用程序会全部暂停。但由于并行回收器使用多线程进行垃圾回收,因此,在并发能力比较强的 CPU 上,它产生的停顿时间要短于串行回收器,而在单 CPU 或者并发能力较弱的系统中,并行回收器的效果不会比串行回收器好,由于多线程的压力,它的实际表现很可能比串行回收器差。
新生代并行回收 (Parallel Scavenge) 收集器 新生代并行回收收集器也是使用复制算法的收集器。从表面上看,它和并行收集器一样都是多线程、独占式的收集器。但是,并行回收收集器有一个重要的特点:它非常关注系统的吞吐量。
老年代并行回收收集器 parallel old 老年代的并行回收收集器也是一种多线程并发的收集器。和新生代并行回收收集器一样,它也是一种关注吞吐量的收集器。老年代并行回收收集器使用标记-压缩算法,JDK1.6 之后开始启用。
-
CMS 收集器 CMS 收集器主要关注于系统停顿时间。CMS 是 Concurrent Mark Sweep 的缩写,意为并发标记清除,从名称上可以得知,它使用的是标记-清除算法,同时它又是一个使用多线程并发回收的垃圾收集器。
-
CMS 工作时,主要步骤有:初始标记、并发标记、重新标记、并发清除和并发重置。其中初始标记和重新标记是独占系统资源的,而并发标记、并发清除和并发重置是可以和用户线程一起执行的。因此,从整体上来说,CMS 收集不是独占式的,它可以在应用程序运行过程中进行垃圾回收。
根据标记-清除算法,初始标记、并发标记和重新标记都是为了标记出需要回收的对象。并发清理则是在标记完成后,正式回收垃圾对象;并发重置是指在垃圾回收完成后,重新初始化 CMS 数据结构和数据,为下一次垃圾回收做好准备。并发标记、并发清理和并发重置都是可以和应用程序线程一起执行的。
-
G1 收集器 G1 收集器是基于标记-压缩算法的。因此,它不会产生空间碎片,也没有必要在收集完成后,进行一次独占式的碎片整理工作。G1 收集器还可以进行非常精确的停顿控制。
网络基本概念
OSI模型
OSI 模型(Open System Interconnection model)是一个由国际标准化组织