面试题(一)——互联网公司面试题整理

百度移动游戏

1.ArrayList和LinkedList区别
2.HashMap实现原理,内部构造,JDK1.8的实现
3.如何设计数据库
4.JVM堆为什么分成年轻代和老年代
5.ConcurrentHashMap原理
6.一个方法中定义一个int型变量和一个Integer变量,这两个变量什么时候会被回收

阿里高德

1.LinkedList是单向链表还是双向链表
2.JVM内存模型
3.GC算法以及回收器(CMS)
4.TCP、UDP、IP、HTTP分别处于哪层

阿里

1.JVM内存模型
2.ZooKeeper选举

爱奇艺

1.CPU100%如何找问题
2.MySQL两种存储引擎(Innodb和MyISAM)的区别
3.Redis和Memecache区别

微博

1.Redis存储一个k-v占多少内存
2.MySQL索引问题,聚簇索引(a,b,c),查询时使用条件b和c是否走索引
3.如何高效的将字符串IP翻译成整数

360面试
1.如何实现一个list,set
2,list如何去重
3.如何实现线程在同一时刻执行
4.线程的实现方式
5.项目的演示
6.hashmap,hashtable的区别

蓝汛

1.redis
2.netty
3.

题目讲解

1.Java类加载器机制
类加载器结构:
引导类加载器(BootstrapClassLoader,原生代码写的,不继承自ClassLoader):加载Java核心库
|/
扩展类加载器(ExtClassLoader,继承自ClassLoader,parent==null):加载Java的扩展库
|/
系统类加载器(SystemClassLoader,继承自ClassLoader,parent==ExtClassLoader):根据 Java 应用的类路径(CLASSPATH)来加载Java类,可以通过 ClassLoader.getSystemClassLoader()来获取它。
类加载过程:
加载类时采用代理机制,当前类加载器首先会让父类加载器进行加载,如果加载不到,在自己加载。web类加载器机制不同,优先自己加载(除Java核心类库外)。
如何开发自己的类加载器:
继承自ClassLoader,重写findClass(),方法内获取到字节码后调用父类的defineClass()即可。不可重写loadClass()(LoadClass内部实现代理机制逻辑)

虚拟机的类加载机制:虚拟机把描述类的数据class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可被虚拟机直接使用的java类
在类装载到一个jvm中需要经过 加载——>链接->初始化
(a)校验:检查载入Class文件数据的正确性;
(b)准备:给类的静态变量分配存储空间;
(c)解析:将符号引用转成直接引用;

2.垃圾回收算法
a.引用计数法
通过对一个对象增加一个计数器方式实现。
优点:实现简单
缺点:无法解决循环引用问题
b.标记-清除算法
通过根节点,标记所有从根节点可达的对象,然后将未被标记的对象进行清除。、
优点:可解决循环引用问题
缺点:造成内存碎片
c.复制算法
将原有内存划分成两块,每次只使用一块,回收时将正在使用的内存中存活的对象复制到另一块内存中,然后清除之前内存中剩余的对象,互换两块内存的角色。
优点:如果存活对象很少,那么需要复制的对象将很少,效率很高,同时内存也会连续
缺点:将内存折半
d.标记-压缩算法
使用标记方式寻找存活对象,然后将存活对象压缩到内存的一端,清理到外界的内存即可。
优点:内存连续
缺点:需要移动对象,所以需要改变很多引用地址
e.增量算法
该算法是为了解决Stop-The-World问题,即进行垃圾收集时需要暂停应用程序,所以为了减少应用程序暂停的时间,将垃圾回收过程分批进行。
有点:降低应用程序暂停时间
缺点:增加线程上下文切换时间,降低系统吞吐率
f.分代
将内存分成不同的块,针对不同内存块对象的特征采用不同的垃圾回收算法。例如:HotSpot将内存分成年轻代和老年代,年轻代的特征是对象量多,但是存活对象较少,适合采用效率较高的复制算法,将存活对象复制到另一块内存,可以解决内存碎片问题;而老年代对象生命周期较长,且对象较大,故适合采用标记-压缩算法。

3.垃圾回收器类型
a.新生代串行收集器(DefNew)
b.老年代串行收集器(DefNew)
c.并行收集器(ParNew)
d.新生代并行回收收集器(PSYoungGen)
e.老年代并行回收收集器(PSYoungGen)
f.CMS收集器
g.G1收集器

4.JVM
a.JVM内存模型:JVM内存模型分成:程序计数器、虚拟机栈、本地方法栈、堆、方法区五个区域
b.程序计数器、虚拟机栈以及本地方法栈属于线程私有,而堆和方法区是线程共享的。
c.程序计数器保存当前线程执行的字节码行号,线程在执行每个方法时都会在虚拟机栈上创建一个栈帧,栈帧中主要保存本地变量表、操作栈等信息,本地方法栈是用于本地方法调用的,如果线程当前执行的是本地方法,那么程序计数器为null。
d.方法区保存Java的类信息、静态变量、JIT编译的本地代码等,常量池在JDK1.7已移到堆中。
e.堆保存着程序运行过程中创建的所有对象信息。堆还可细分成:年轻代和老年代,年轻代还可细分为:一个eden区和两个survivor区(from和to)。对象的创建是在eden区,大对象有可能直接在老年代创建。
f.针对年轻代和老年代对象的不同特征,垃圾回收器对年轻代采用复制算法,而老年代采用标记-压缩算法。年轻代由于存活对象不多,而且对象较小,直接采用复制算法会有很高的效率;老年代由于存活对象较多,且对象较大,使用标记算法较好,同时为了避免比较算法产生的碎片,采用压缩算法进行压缩。

5.类加载机制
1)类加载时机
主动引用
a.new对象、访问类的静态属性与调用类的静态方法时
b.反射调用时
c.初始化类时,需先初始化父类
d.虚拟机启动时需指定一个主类,虚拟机会先初始化该类
被动引用
a.使用子类访问父类的静态变量或调用父类静态方法时只会初始化父类,不会初始化子类
b.定义一个该类的数组并不会引发类的初始化
c.引用类的常量(final static)不会引发类的初始化,因为常量会被保存到常量池,所以引用常量直接引用常量池,并不通过类

2)类加载过程
加载–>验证–>准备–>解析–>初始化
加载通过类加载器进行加载,代理方式
验证主要用于对class内容进行安全性校验
准备是在方法区为类分配内存,并将类属性置0
解析将字符串常量池内的符号引用替换为直接引用
初始化主要是对类的初始化,即为静态变量赋值,执行静态语句块
3)强引用,弱引用和软引用

6.文件读取过程
a.确定所请求的数据分布于文件系统的哪些页
b.在内核空间分配足够的内存页,以容纳确定的文件系统页
c.在内存页与文件系统页之间建立映射关系
d.通过虚拟内存将页面调入,从磁盘上读取页面内容
e.页面调入完成,文件系统对原始数据进行解析,取得所需文件内容或属性信息

7.NIO
1)文件锁:
文件锁是针对进程级别的,如果一个JVM中有一个线程已获取文件锁,另一个线程再获取就会抛出OverlappingFileLockException异常。请求两个共享锁也不行。
2)NIO与IO的区别:
数据打包与传输的方式不同。旧的IO以流的方式处理数据,而NIO以块的方式处理数据。现代的操作系统都是按块从磁盘获取数据,所以NIO将比旧IO在数据处理上效率高很多。

8.Http协议
1)请求内容:
请求行:方法 URI 版本号 POST /reg.jsp HTTP/ (CRLF)
请求头(消息头):请求头包含如Content-Length、Accept等参数
请求体(消息正文):传递的数据,如POST的内容
2)响应内容:
状态行:服务器Http版本号 状态码 状态代码描述
响应头:
响应体:

8.Java代码优化
普通代码方面:
1)在集合的长度可知情况下使用带有指定初始化容量的集合构造器
2)单线程情况下使用非线程安全的类,而非线程安全的,如StringBuffer和HashTable
3)避免错误使用异常机制,除非是是在无法判断是否会发生异常的情况下才使用,如可预先判断异常状态则预先进行条件判断而避免使用异常机制
4)尽量使用final常量,避免过多的使用static变量(由于static变量和方法很难回收,需要回收该Class信息,需回收对应的ClassLoader)
5)尽量使用局部变量,因为局部变量保存在栈中,访问速度高于堆
并发方面:
1)尽量使用线程池,并合理设置线程池的大小,如CPU密集型任务使用CPU+1,IO密集型任务使用2*CPU
2)不要轻易使用锁,降低锁的粒度,合理使用读写锁
3)使用JDK提供的高效的并发工具类,如J.U.C下的并发集合类,以及原子类

9.redis和memcached区别
1)redis支持丰富的数据类型,memcached仅支持单一的k-v数据类型
2)redis支持数据持久化,如AOF和RBD,memcached不支持,重启后数据就全部丢失
3)memcached支持CAS,redis只能通过将多个操作组合到一起顺序执行的方式实现很简单的事务机制

10.mysql两个存储引擎区别
InnoDB支持事务和行级锁以及外键
MyISAM不支持事务和行级锁以及外键,只支持表锁

11.CPU100%如何分析
通过top -H查看CPU占用率最高的线程ID,找到线程ID之后,可以通过JDK提供的JVM监控工具,如jstack将线程的堆栈信息打印出来(需要将十进制的线程ID转成16进制)。
一般占用CPU很高的情况有:
1)死循环
2)密集型计算

12.如何设计数据库
1.表名要能体现出属性的含义
2.动静分离,将一个表的变化的属性与不变的属性分开

13.数据库索引问题
1. MySQL仅能对索引最左边的前缀进行有效的查找
例如:索引(a,b),select * from table where a = a1 and b = b1和select * from table where a = a1可以走索引,但是select * from table where b = b1不走索引, 因为没有组合索引的引导列
2.支付范围查询

? and < ?或者>?或者

猜你喜欢

转载自blog.csdn.net/xhwwc110/article/details/80066416