文章目录
一、自我介绍
个人背景、项目经历、实习经历。
二、Java后台
2.1 计算机网络
2.1.1 http访问请求过程
- 输入网址
www.baidu.com
。www万维网,baidu是域名,com是域名类型。 - DNS(Domain Name System,域名系统)查询,浏览器根据域名通过
DNS服务器
查询域名对应的服务器的IP地址:
浏览器缓存中-> 系统缓存 -> 路由器缓存 -> 本地DNS服务器 -> 根域名服务器
。 - 浏览器主机根据IP地址与服务器建立
TCP连接
,浏览器发送请求至服务器(浏览器向重定向后的地址发送请求),浏览器将访问请求封装为一个http请求报文
,通过TCP协议
发送给服务器。 - 服务器处理http请求。
- 服务器返回http响应,生成一个
http响应报文
,通过TCP协议
发送给浏览器主机。 - 浏览器请求样式以及图片文件,用以
渲染界面(Ajax)
并显示给用户。 - 浏览器异步请求其他资源。
2.1.2 http界面渲染过程
- 解析HTML
- 构建DOM树(DOM,Document Object Model,文档对象模型)
DOM树的构建过程是一个深度遍历过程:当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点。 - 解析CSS构造CSSOM树(CSSOM,CSS Object Model,CSS对象模型)
- DOM树与CSSOM构造渲染树
- 布局
计算出每个节点在屏幕中的位置。 - 绘制
遍历渲染树,并使用浏览器UI后端层绘制每个节点。
2.1.3 什么是端口
端口:就好像门牌号一样,客户端可以通过IP地址找到对应的服务器端,但是服务器端有很多端口,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到该服务器。
2.1.4 TCP拥塞控制
拥塞控制:防止过多的数据注入到网络当中,使网络中的路由器或链路不致过载。是通过拥塞窗口处理网络拥塞现象的一种机制。
四种方法:
- 慢启动
当主机开始发送数据时,如果立即将大量数据字节注入到网络,那么有可能因为不清楚当前网络的负荷情况而引起网络阻塞。所以先探测一下,由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。 - 拥塞避免
让拥塞窗口cwnd缓慢的增大,即每经过一个往返时间RTT把发送方的拥塞窗口cwnd加1,而不是加倍,这样拥塞窗口cwnd按线性规律缓慢的增长,比慢开始算法的拥塞窗口增长速率缓慢的多。 - 快重传
快重传算法要求首先接收方收到一个失序的报文段后立刻发出重复确认,而不要等待自己发送数据时才进行捎带确认。 - 快恢复
当发送方连续收到三个重复确认时,执行“乘法减小”算法,慢启动门限减半,预防网络发生阻塞。
2.2 JVM内存
2.2.1 GC机制、算法
- GC机制
(1)引用计数法:通过引用计数来判断一个对象是否可以回收。即一个对象如果没有任何与之关联的引用, 即他们的引用计数都不为0,则说明对象不太可能再被用到,那么这个对象就是可回收对象。
(2)可达性分析:为了解决引用计数法的循环引用问题,Java使用了可达性分析的方法。通过一系列的GC roots对象作为起点搜索。如果在GC roots和一个对象之间没有可达路径,则称该对象是不可达的。不可达对象经过两次标记为可回收对象,则将面临回收。 - GC算法
(1)标记清除算法:分为两个阶段,标记阶段标记需要回收的对象,清除阶段回收对象占用的空间。
(2)复制算法:按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉。
(3)标记整理算法:标记阶段和标记清除算法相同, 标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。
(4)分代收集算法:新生代采用复制算法、老年代采用标记整理算法。
2.3 Java多线程
2.3.1 多线程注意事项
- 线程使用中注意如何控制线程的调度和阻塞,例如利用事件的触发来控制线程的调度和阻塞,也有用消息来控制的。
- 线程中如果用到公共资源,一定要考虑公共资源的线程安全性。一般用Lock锁机制来控制线程安全性。要保证不要有死锁机制。
- 合理使用Sleep,何时Sleep,Sleep的大小要根据具体项目,做出合理安排。一般原则非阻塞状态下每个循环都要有Sleep,这样保证减少线程对CPU的抢夺。每次线程的就绪和激活都会占用一定得资源,如果线程体如果有多个循环,多处使用Sleep将导致性能的下降。
- 线程的终止一般要使线程体在完成一件工作的情况下终止,一般不要直接使用抛出线程异常的方式终止线程。
- 线程的优先级一定根据程序的需要要有个整体的规划。
2.3.2 线程死锁原因
- 互斥条件:一个资源每次只能被一个进程使用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
- 循环等待:若干进程之间形成一种头尾相接的循环等待资源的的关系。
2.3.3 多线程生产者消费者模型
生产者消费者模式是并发、多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据。
- 方法一:wait()和notify()通信方法实现。
- 方法二:阻塞队列实现生产者消费者模式。
优点:
- 简化开发,可以独立地或并发的编写消费者和生产者,仅仅只需知道共享对象。
- 生产者不需要知道谁是消费者或者有多少消费者,对消费者来说也是一样
- 生产者和消费者可以以不同的速度执行
- 分离的消费者和生产者在功能上能写出更简洁、可读、易维护的代码
三、移动端开发
3.1 自定义view
见其他面经:
(1)面试笔记:面经-腾讯-一面
3.2 activity和view的关系
view组件是Android用户实实在在看得到的部分,但是view组件需要放到容器组件中去,或者使用activity将他显示出来,如果需要某个activity把制定的view显示出来,需要调用activity的setContentView()方法
。
3.3 Android动画
- 逐帧动画
原理就是让一系列的静态图片依次播放,利用人眼“视觉暂留”的原理,实现动画。 - 补间动画
指开发者指定动画的开始、动画的结束的"关键帧",而动画变化的"中间帧"由系统计算,并补齐。
淡入淡出(alpha)
、位移(translate)
、缩放(scale)
、旋转(rotate)
。 - 属性动画
可以看作是增强版的补间动画,与补间动画的不同之处体现在:
(1)补间动画只能定义两个关键帧在透明、旋转、位移和倾斜这四个属性的变换;属性动画可以定义任何属性的变化。
(2)补间动画只能对 UI 组件执行动画;属性动画可以对任何对象执行动画。
3.4 Android Handler
Handler是用来结合线程的消息队列来发送、处理“Message对象”和“Runnable对象”的工具。每一个Handler实例之后会关联一个线程
和该线程的消息队列
。当创建一个Handler之后,它就会自动关联到所在的线程/消息队列,然后陆续把Message/Runnalbe分发到消息队列,并在它们出队的时候处理掉。
- Handler主要用途:
(1)推送未来某个时间点将要执行的Message或者Runnable到消息队列。
(2)在子线程把需要在另一个线程执行的操作加入到消息队列中去。
3.5 Android优化ListView
- 在adapter中的getView方法中尽量少使用逻辑。
- 尽最大可能避免GC。
- 滑动的时候不载入图片。
- 将ListView的scrollingCache和animateCache设置为false。
- item的布局层级越少越好。
- 使用ViewHolder。
3.6 Android优化画面卡顿
卡顿:假设更新屏幕的背景图片需要24ms做运算,界面刷新周期为16ms,当系统在第一个16ms时刷新界面,由于运算还没有结束,无法绘出图片。当系统隔16ms再发一次VSYNC信息重绘界面时,用户才会看到更新后的图片。也就是说32ms后才看到了这次刷新(并不是24ms),这就是丢帧(dropped frame)
。丢帧给用户的感觉就是卡顿,而且如果运算过于复杂,丢帧会更多,导致界面常常处于停滞状态。
- 卡顿原因
(1)过于复杂的布局。
(2)过度绘制。
(3)UI线程的复杂运算。
(4)频繁的GC。 - 优化方法
(1)减少刷新次数。
(2)避免非必要的刷新。
(3)避免后台线程影响。
(4)局部刷新
(5)尽量使用属性动画,减少自身的重绘。最后要清除。
(6)StringBuilder,List等在创建时传入一个合适的参数指定初始容量,以避免频繁扩容的开销。
(7)开启硬件加速。
3.7 Android打开网页
- 方法一:通过系统自带的浏览器访问。
- 方法二:通过APP内部打开网页,WebView控件 。
四、算法题(手撕)
4.1 大数乘法
见其他面经:
(1)面试笔记:面经-腾讯-一面