面试(操作系统、网络、java)

一、操作系统

1.什么是进程和线程,有何区别?
进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程是进城的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。
进程与应用程序的区别在于应用程序作为一个静态文件存储在计算机系统的硬盘灯存储空间中,而进程则是处于动态条件下由操作系统维护的系统资源管理实体。

2.什么是临界区,如何解决冲突?
每个进程中访问临界资源的那段程序称为临界区,每次只准许一个进程进入临界区,进入后不允许其他进程进入。
1)如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
2)任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其他所有试图进入临界区的进程必须等待。
3)进入临界区的进程要在有限时间内退出,以便其他进程能及时进入自己的临界区。
4)如果进程不能进入自己的临界区,则应让出CPU,避免进程出现忙等现象。

3.进程通信有哪些方式?
管道通信,消息通信,内存共享

4.进程同步的方法
内存屏障,互斥锁,信号量和锁,管程,消息,管道

5.linux系统常用的命令

6.什么死锁,死锁的条件,怎样避免死锁?
死锁的概念:在两个或多个并发进程中,如果每个进程持有某种资源而又都等待别的进程释放它们现在保持着的资源,否则就不能向前推进。此时,每个进程都占用了一定的资源但是又不能向前推进,称这一组进程产生了死锁。通俗的讲,就是两个或多个进程无止境的等候着永远不会成立的条件的一种系统状态。
死锁产生的主要原因是:1)系统资源不足;2)进行运行推进的顺序不合理;3)资源分配不当
产生死锁的必要条件:1)互斥,一个资源每次只能被一个进程使用;2)占有且等待,一个进程因请求资源而阻塞时,对已获得的资源保持不放;3)不可抢占,进程已获得的资源,在未使用完之前,不能强行剥夺;4)环形等待,若干进程之间形成一种首尾相接的循环等待资源关系。这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
死锁的解除与预防:理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源。因此对资源的分配要给予合理的规划。

7.Windows下的内存是如何管理的?
Windows提供了3种方法来进行内存管理:虚拟内存,最适合用来管理大型对象或者结构数组;内存映射文件,最适合用来管理大型数据流(通常来自文件)以及在单个计算机上运行多个进程之间共享数据;内存堆栈,最适合用来管理大量的小对象。
Windows操纵内存可以分两个层面:物理内存和虚拟内存。
其中物理内存由系统管理,不允许应用程序直接访问,应用程序可见的只有一个2G地址空间,而内存分配是通过堆进行的。对于每个进程都有自己的默认堆,当一个堆创建后,就通过虚拟内存操作保留了相应大小的地址块(不占有实际的内存,系统消耗很小)。当在堆上分配一块内存时,系统在堆的地址表里找到一个空闲块(如果找不到,且堆创建属性是可扩充的,则扩充堆大小),为这个空闲块所包含的所有内存页提交物理对象(在物理内存上或硬盘的交换文件上),这时就可以访问这部分地址。提交时,系统将对所有进程的内存统一调配,如果物理内存不够,系统试图把一部分进程暂时不访问的页放入交换文件,以腾出部分物理内存。释放内存时,只在堆中将所在的页解除提交(相应的物理对象被解除),继续保留地址空间。
如果要知道某个地址是否被占用/可不可以访问,只要查询此地址的虚拟内存状态即可。如果是提交,则可以访问。如果仅仅保留,或没保留,则产生一个软件异常。此外,有些内存页可以设置各种属性。如果是只读,向内存写也会产生软件异常。

8.说说分段和分页
页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外零头,提高内存的利用率;或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。
段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了能更好的满足用户的需要。
页的大小固定且由系统确定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而一个系统只能有一种大小的页面。段的长度却不固定,决定于用户所编写的程序,通常由编辑程序在对源程序进行编辑时,根据信息的性质来划分。
分页的作业地址空间是一维的,即单一的线性空间,程序员只须利用一个记忆符,即可表示一地址。分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。

9.什么是中断?中断时CPU做什么工作?
中断是指在计算机执行期间,系统内发生任何非寻常的或非预期的急需处理事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序。待处理完毕后又返回原来被中断处继续执行或调度新的进程执行的过程。

10.什么是缓冲区溢出?有什么危害?其原因是什么?
缓冲区溢出是指当计算机向缓冲区填充数据时超出了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
危害有以下两点:
程序崩溃,导致拒绝额服务
跳转并且执行一段恶意代码
造成缓冲区溢出的主要原因是程序中没有仔细检查用户输入。

11.操作系统中进程调度策略有哪几种?
(1)先来先服务(FCFS,First-Come-First-Served): 此算法的原则是按照作业到达后备作业队列(或进程进入就绪队列)的先后次序来选择作业(或进程)。
(2)短作业优先(SJF,Shortest Process Next):这种调度算法主要用于作业调度,它从作业后备队列中挑选所需运行时间(估计值)最短的作业进入主存运行。
(3)时间片轮转调度算法(RR,Round-Robin):当某个进程执行的时间片用完时,调度程序便停止该进程的执行,并将它送就绪队列的末尾,等待分配下一时间片再执行。然后把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片。这样就可以保证就绪队列中的所有进程,在一给定的时间内,均能获得一时间片处理机执行时间。
(4)高响应比优先(HRRN,Highest Response Ratio Next): 按照高响应比((已等待时间+要求运行时间)/ 要求运行时间)优先的原则,在每次选择作业投入运行时,先计算此时后备作业队列中每个作业的响应比RP然后选择其值最大的作业投入运行。
(5)优先权(Priority)调度算法: 按照进程的优先权大小来调度,使高优先权进程得到优先处理的调度策略称为优先权调度算法。注意:优先数越多,优先权越小。
(6)多级队列调度算法:多队列调度是根据作业的性质和类型的不同,将就绪队列再分为若干个子队列,所有的作业(或进程)按其性质排入相应的队列中,而不同的就绪队列采用不同的调度算法。

扫描二维码关注公众号,回复: 2808211 查看本文章

12.进程同步与互斥的区别
互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。
简单地说:同步体现的是一种协作性,互斥体现的是一种排他性。
附注补充: 
  进程同步的主要任务:是对多个相关进程在执行次序上进行协调,以使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。
  同步机制遵循的原则:
  (1)空闲让进;
  (2)忙则等待(保证对临界区的互斥访问);
  (3)有限等待(有限代表有限的时间,避免死等);
  (4)让权等待(当进程不能进入自己的临界区时,应该释放处理机,以免陷入忙等状态)。
  线程同步指多个线程同时访问某资源时,采用一系列的机制以保证同时最多只能一个线程访问该资源。线程同步是多线程中必须考虑和解决的问题,因为很可能发生多个线程同时访问(主要是写操作)同一资源,如果不进行线程同步,很可能会引起数据混乱,造成线程死锁等问题。
线程同步的方式:
临界区:通过对多线程的串行化来访问公共资源或者一段代码,速度快,适合控制数据访问
互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以可以保证公共资源不会同时被多个线程访问
信号量:它允许多个线程同一时刻访问同一资源,但是需要限制同一时刻访问此资源的最大线程数目。信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中PV操作相似。
事件(信号):通过通知操作的方式来保持多线程的同步,还可以方便的实现多线程的优先级比较的操作

二、计算机网络

1.HTTP是网络七层协议中哪一层的协议?
参考答案:应用层。
解题思路:基础知识
考察点:OSI七层协议的基础知识 分类:HTTP,基础知识,网络,{校招,社招都可以用} 难度分级:P4

2.UDP,TCP是网络七层协议中哪一层的协议,区别是什么,分别适用于什么场景?
参考答案:
传输层。 在TCP/IP模型中,传输层的功能是使源端主机和目标端主机上的对等实体可以进行会话。
在传输层定义了两种服务质量不同的协议。即:传输控制协议TCP(transmission control protocol)和用户数据报协议UDP(user datagram protocol)。
TCP协议是一个面向连接的、可靠的协议。它将一台主机发出的字节流无差错地发往互联网上的其他主机。 需要三次握手建立连接,才能进行数据传输。在发送端,它负责把上层传送下来的字节流分成报文段并传递给下层。 在接收端,它负责把收到的报文进行重组后递交给上层。TCP协议还要处理端到端的流量控制,以避免缓慢接收的接收方没有足够的缓冲区接收发 送方发送的大量数据。 UDP协议是一个不可靠的、无连接协议,不与对方建立连接,而是直接就把数据包发送过去。主要适用于不需要对报文进行排序和流量控制的 场合。 UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。比如,我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常, 其 实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是 通的。
解题思路:基础知识,从面向连接、可靠性、应用场合上进行分析对比 考察点:七层协议中传输层的基础知识,着重从TCP vs UDP的区别上考察 分类:七层协议,基础知识,网络,{校招,社招都可以用} 难度分级:P4,P5

3.TCP对应的协议和UDP对应的协议
TCP对应的协议:
(1) FTP:定义了文件传输协议,使用21端口。常说某某计算机开了FTP服务便是启动了文件传输服务。下载文件,上传主页,都要用到FTP服务。
(2) Telnet:它是一种用于远程登陆的端口,用户可以以自己的身份远程连接到计算机上,通过这种端口可以提供一种基于DOS模式下的通信服务。如以前的BBS是-纯字符界面的,支持BBS的服务器将23端口打开,对外提供服务。
(3) SMTP:定义了简单邮件传送协议,现在很多邮件服务器都用的是这个协议,用于发送邮件。如常见的免费邮件服务中用的就是这个邮件服务端口,所以在电子邮件设置-中常看到有这么SMTP端口设置这个栏,服务器开放的是25号端口。
(4) POP3:它是和SMTP对应,POP3用于接收邮件。通常情况下,POP3协议所用的是110端口。也是说,只要你有相应的使用POP3协议的程序(例如Fo-xmail或Outlook),就可以不以Web方式登陆进邮箱界面,直接用邮件程序就可以收到邮件(如是163邮箱就没有必要先进入网易网站,再进入自己的邮-箱来收信)。
(5)HTTP协议:是从Web服务器传输超文本到本地浏览器的传送协议。
UDP对应的协议:
(1) DNS:用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。
(2) SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
(3) TFTP(Trival File Transfer Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。

4.TCP三次握手?能不能改成两次?
建立连接的过程是利用客户服务器模式,假设主机 A 为客户端,主机 B 为服务器端。
( 1 ) TCP 的三次握手过程:主机 A 向 B 发送连接请求;主机 B 对收到的主机 A 的报文段进行确认;主机 A 再次对主机 B 的确认进行确认。
( 2 )采用三次握手是为了防止失效的连接请求报文段突然又传送到主机 B ,因而产生错误。失效的连接请求报文段是指:主机 A 发出的连接请求没有收到主机 B 的确认,于是经过一段时间后,主机 A 又重新向主机 B 发送连接请求,且建立成功,顺序完成数据传输。考虑这样一种特殊情况,主机 A 第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到主机 B ,主机 B 以为是主机 A 又发起的新连接,于是主机 B 同意连接,并向主机 A 发回确认,但是此时主机 A 根本不会理会,主机 B 就一直在等待主机 A 发送数据,导致主机 B 的资源浪费。
( 3 )采用两次握手不行,原因就是上面说的实效的连接请求的特殊情况。

5.TCP的可靠性如何保证?
在TCP的连接中,数据流必须以正确的顺序送达对方。TCP的可靠性是通过顺序编号和确认(ACK)来实现的。TCP在开始传送一个段时,为准备重传而首先将该段插入到发送队列之中,同时启动时钟。其后,如果收到了接受端对该段的ACK信息,就将该段从队列中删去。如果在时钟规定的时间内,ACK未返回,那么就从发送队列中再次送出这个段。TCP在协议中就对数据可靠传输做了保障,握手与断开都需要通讯双方确认,数据传输也需要双方确认成功,在协议中还规定了:分包、重组、重传等规则;而UDP主要是面向不可靠连接的,不能保证数据正确到达目的地。

6.ping命令使用的是什么协议
ICMP

7.ARP协议的工作原理
首先,每台主机都会在自己的ARP缓冲区中建立一个 ARP列表,以表示IP地址和MAC地址的对应关系。当源主机需要将一个数据包要发送到目的主机时,会首先检查自己 ARP列表中是否存在该 IP地址对应的MAC地址,如果有,就直接将数据包发送到这个MAC地址;如果没有,就向本地网段发起一个ARP请求的广播包,查询此目的主机对应的MAC地址。此ARP请求数据包里包括源主机的IP地址、硬件地址、以及目的主机的IP地址。网络中所有的主机收到这个ARP请求后,会检查数据包中的目的IP是否和自己的IP地址一致。如果不相同就忽略此数据包;如果相同,该主机首先将发送端的MAC地址和IP地址添加到自己的ARP列表中,如果ARP表中已经存在该IP的信息,则将其覆盖,然后给源主机发送一个 ARP响应数据包,告诉对方自己是它需要查找的MAC地址;源主机收到这个ARP响应数据包后,将得到的目的主机的IP地址和MAC地址添加到自己的ARP列表中,并利用此信息开始数据的传输。如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。

8.在浏览器中输入网址后执行的全部过程
1).查找域名对应的IP地址。这一步会依次查找浏览器缓存,系统缓存,路由器缓存,ISPNDS缓存,根域名服务器。
2).向IP对应的服务器发送请求。
3).服务器响应请求,发回网页内容。
4).浏览器解析网页内容。
由于网页可能有重定向,或者嵌入了图片,AJAX,其它子网页等等,这4个步骤可能反复进行多次才能将最终页面展示给用户。

9.cookie 和session 的区别
cookie数据存放在客户的浏览器上,session数据放在服务器上。
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
个人建议:
将登陆信息等重要信息存放为SESSION
其他信息如果需要保留,可以放在COOKIE中

10.TCP的流量控制和拥塞处理
http://www.cnblogs.com/xxiaoye/p/3680849.html

三、算法相关

1.二叉树先序遍历
给一个二叉树的先序遍历和中序遍历,然后给出后序遍历。递进一步:前序、中序、后序三种遍历,任意给出两能求出第三个嘛

2.汉诺塔问题
解法:http://www.runoob.com/java/method-tower.html

代码块

Plain Text

public class MainClass {
    public static void main(String[] args) {
        int nDisks = 3;
        doTowers(nDisks, 'A', 'B', 'C');
    }
    public static void doTowers(int topN, char from, char inter, char to) {
        if (topN == 1){
            System.out.println("Disk 1 from " + from + " to " + to);
        }else {
            doTowers(topN - 1, from, to, inter);
            System.out.println("Disk " + topN + " from " + from + " to " + to);
            doTowers(topN - 1, inter, from, to);
        }
    }
}

3.求二叉树中第k层节点的个数

4.求二叉树中任意两个节点的第一个公共父节点

5.随意给定一个字符串,将其转换成数字
考察思维完整性,代码需要判断有没有 字母、正符号、小数点,数字过大当前类型存放不了。
当面试者问你是否有字母、负号等的时候,只需声明题目就这一句话,让起自由发挥。考察应聘者是否只想简单化问题,怕麻烦。

6.给一组数,只有两个数只出现了一次,其他所有数都是成对出现的。怎么找出这两个数。编写函数实现。
对于一组数中只有一个数只出现一次,其他所有数都是成对出现的,我们采用了对全部数组元素进行异或,但是对于找出两个出现一次的数应该怎么解决呢?先对所有的元素进行异或,则结果为两个出现一次的数的异或结果,然后将结果转换为二进制,找出二进制数中的第一个1,然后根据这个1的判断条件进行分组,分为两组,分别对两个组的元素进行全部异或,则就找出两个不同的数。

题目分析:

上次介绍了,对于一组数中只有一个数只出现一次,其他所有数都是成对出现的,我们采用了对全部数组元素进行异或,但是对于找出两个出现一次的数应该怎么解决呢?先对所有的元素进行异或,则结果为两个出现一次的数的异或结果,然后将结果转换为二进制,找出二进制数中的第一个1,然后根据这个1的判断条件进行分组,分为两组,分别对两个组的元素进行全部异或,则就找出两个不同的数。

7.使用两个栈实现一个队列,能用两个队列实现一个栈吗?

8. 求数字集合所有子集 (递归和循环时间复杂度分析)

9.判断出栈序列,输入两个整数序列。其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序。

10.给定一个数字数组d和数字a,其中数组d中数字顺序先下降后递增,找到数字a在数组d中的下标(如果没有则返回-1)。
主要考查是否掌握基本的二分查找方法,逻辑思维能力,以及运用现有知识解决新问题的能力。

11.寻找数组中相加为0的组合,给定一个int数组[1,-1,0,2,-1,4],要求找出数组中,所有的三元组,符合相加为0的特性。比如[-1,-1,2]和[1,-1,0]

四、数据库

1.事务四大特性、隔离级别及其影响
四大特性:
1)原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
2)一致性(Consistency)
 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
3)隔离性(Isolation)
 隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
 即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
 关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。
4)持久性(Durability)
 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
事务隔离级别
1)Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
2)Repeatable read (可重复读):可避免脏读、不可重复读的发生。
3)Read committed (读已提交):可避免脏读的发生。
4)Read uncommitted (读未提交):最低级别,任何情况都无法保证。
影响:
1)脏读
脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
 当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。例如:用户A向用户B转账100元,对应SQL命令如下
update account set money=money+100 where name=’B’; (此时A通知B)
update account set money=money - 100 where name=’A’;
 当只执行第一条SQL时,A通知B查看账户,B发现确实钱已到账(此时即发生了脏读),而之后无论第二条SQL是否执行,只要该事务不提交,则所有操作都将回滚,那么当B以后再次查看账户时就会发现钱其实并没有转。
2)不可重复读
 不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
 例如事务T1在读取某一数据,而事务T2立马修改了这个数据并且提交事务给数据库,事务T1再次读取该数据就得到了不同的结果,发送了不可重复读。
 不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
 在某些情况下,不可重复读并不是问题,比如我们多次查询某个数据当然以最后查询得到的结果为主。但在另一些情况下就有可能发生问题,例如对于同一个数据A和B依次查询就可能不同,A和B就可能打起来了……
3)虚读(幻读)
 幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
 幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

2.为什么MySQL的索引要使用B+树而不是其它树形结构?为什么不用B树
参考答案:
为什么不用B树?:因为B树的所有节点都是包含键和值的,这就导致了每个几点可以存储的内容就变少了,出度就少了,树的高度会增高,查询的 时候磁盘I/O会增多,影响性能。由于B+Tree内节点去掉了data域,因此可以拥有更大的出度,拥有更好的性能。
解题思路:Mysql 索引数据结构
考察点: Mysql索引数据结构,B+树 B-树 分类:Mysql、数据结构{校招,社招} 难度分级:P4,P5

3.为什么InnoDB中表的主键最好要自增?
InnoDB使用聚集索引,数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的 各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(Inno DB默认为15/16),则开辟一个新的页(节点)。如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置, 当一页写满,就会自动开辟一个新的页。这样就会形成一个紧凑的索引结构,近似顺序填满。由于每次插入时也不需要移动已有数据,因此效率很 高,也不会增加很多开销在维护索引上。
如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此 时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增 加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。
因此,只要可以,请尽量在InnoDB上采用自增字段做主键。 解题思路:InnoDB 主键选择
考察点:InnoDB 索引数据结构,Mysql应用技能 分类:Mysql{校招,社招}

4.MySQL联合索引使用是有什么规则?如果对A,B,C做索引,那么SQL语句写成where C=X and B=X and A=X,是否还能用到该索引?如果SQL语句写成where A=X and B>X and C=X是否还能用到该索引?
参考答案:
联合索引有最左前缀匹配原则。
where C=X and B=X and A=X能用到该索引,因为=和in可以乱序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。
where A=X and B>X and C=X可以用到该索引,但C是用不到索引的,因为mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配。
解题思路:联合索引最左前缀匹配原则
考察点: 是否对联合索引的匹配原则,以及所以的数据结构有过了解
分类:Mysql索引基础知识{校招,社招}
难度分级:P4,P5

5.Btree+和Hash索引有什么区别?
参考答案:
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
可能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢?任何事物都是有两面性的,Hash 索引也一样,虽然 Hash 索引效率高,但是 Hash 索引本身由于其特殊性也带来了很多限制和弊端,主要有以下这些。
(1)Hash 索引仅仅能满足"=","IN"和"<=>"查询,不能使用范围查询。
由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和Hash运算前完全一样。
(2)Hash 索引无法被用来避免数据的排序操_=9C。
由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且Hash值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;
(3)Hash 索引不能利用部分索引键查询。
对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。
(4)Hash 索引在任何时候都不能避免表扫描。
前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。
(5)Hash 索引遇到大量Hash值相等的情况后性能并不一定就会比B-Tree索引高。
对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。
hash相当于把key通过hash函数计算,得到key的hash值,再用这个hash值做指针,查找hash表中是否存在key,如果存在就返回 key所对应的value,选定一个好的hash函数很重要,好的hash函数可以使计算出的hash值分布均匀,降低冲突,只有冲突减小了,才会降低 hash表的查找时间。
b-tree完全基于key的比较,和二叉树相同的道理,相当于建个排序后的数据集,使用二分法查找算法,实际上也非常快,而且受数据量增长影响非常小。

五、系统设计,海量数据处理

1.给40亿个不重复的unsigned int的整数,没排过序,然后再给一个数,如何快速判断这个数是否在那40亿个数中?
bitmap,用位图/Bitmap的方法,申请512M的内存,一个bit为代表一个unsigned int值。读入40亿个数,设置相应的bit位,读入要查询的书,查看相应bit位是否为1,为1表示存在,为0表示不存在。

六、Java基础

1.jdk的类加载机制和类似tomcat类web容器的类加载机制的不同
参考答案:http://blog.csdn.net/codolio/article/details/5027423
解题思路:基础知识
考察点:java类加载机制、web容器类加载机制
难度分级:P2-3

2.浅克隆和深克隆?深克隆的方法?
参考答案:
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
深克隆的方法:Cloneable接口、序列化的方法
http://www.itzhai.com/java-based-notebook-the-object-of-deep-and-shallow-copy-copy-copy-implement-the-cloneable-interface-serializing-deep-deep-copy.html
解题思路:基础知识
考察点:java基础知识
难度分级:P2-3

3.Java 泛型的实现原理是什么?
参考答案:
Java的泛型是伪泛型,Java中的泛型基本上都是在编译器这个层次来实现的,在生成的Java字节码中是不包含泛型中的类型信息的,使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉;
范型 展开原码
public void test(List<String> ls) {
}
public void test(List<Integer> li) {
}
以上代码会编译报错,报错信息为:Erasure of method test(List<String>) is the same as another method in type;
解题思路:范型类型擦除概念
考察点:java基础知识
难度分级:P4,P5

4.泛型的使用场景
参考答案:
JAVA中泛型的使用:java中集合使用了泛型,Future<T>,WeakReference<T>,Class<T>也都使用了泛型
一些使用场景:
不想写多个重载函数的场景。
约束对象类型的场景,可以定义边界(T extends ...),如JDK集合List,Set。
用户希望返回他自定义类型的返回值场景,如Json返回Java bean。
在用反射的应用中,也经常会用到泛型,如Class<T>。
对网页,对资源的分析,返回场景,一般都有泛型。
解题思路:基础知识
考察点:java基础知识
难度分级:P4, P5

5.Integer缓存?Integer比较大小注意问题。==和equals的区别考察
参考答案:
Integer是有缓冲池的,java.lang.Integer.valueOf(int)方法默认情况下如果参数在-128到127之间,则返回缓存中的对象,否则返回new Integer(int)。java使用该机制是为了达到最小化数据输入和输出的目的,这是一种优化措施,提高效率
其他的包装器:
Boolean: (全部缓存)
Byte: (全部缓存)
Character ( <=127 缓存)
Short (-128~127 缓存)
Long (-128~127 缓存)
Float (没有缓存)
Doulbe (没有缓存)
可以设置系统属性 java.lang.Integer.IntegerCache.high 修改缓冲区上限,默认为127。参数内容应为大于127的十进制数形式的字符串,否则将被忽略。取值范围为127-Long.MAX_VALUE,但是用时将强转为int。当系统中大量使用Integer时,增大缓存上限可以节省小量内存。
区别“==”和equals():“==”是比较两个对象是不是引用自同一个对象。 “equals()”是比较两个对象的内容。
解题思路:基础知识
考察点:java基础知识
难度分级:P4

6.自动装箱机制,阅读以下代码,指出有问题的地方
展开原码
public static void testNotNullPointer() {
Integer numNull;
int numInt = 1;
int numInt2 = 2;
Integer numInteger = null;
//if else
if (numInt == 1) {
numInt2 = numInteger; // numInteger为null赋值给int类型变量,自动解箱时报空指针异常
} else {
numNull = numInt2;
}
//三目运算符和if else的区别, numInteger为null参与三目运算时,自动解箱时报空指针异常
numNull = numInt == 1 ? numInteger : numInt2;
参考答案:
http://developer.51cto.com/art/201203/325314.htm
解题思路:基础知识
考察点:java基础知识
难度分级:P4

7.java的类加载器体系结构和双亲委托机制,应用场景举例
参考答案:
http://blog.csdn.net/lovingprince/article/details/4317069
解题思路:java类加载机制
考察点:java类加载机制
难度分级:P4, P5

8.红黑树有哪些特性,在Java源码中那部分有应用?
参考答案:
红黑树是一种类平衡树,但不是一种严格的平衡二叉树, 红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。对比AVL,红黑树查找的性能比AVL稍差,但插入删除稍好(平衡操作最多旋转3次)。
java源码中的应用:TreeMap和TreeSet是利用红黑树实现的
关于红黑树可以参考:
http://blog.csdn.net/v_july_v/article/details/6105630
解题思路:基础知识
考察点:java基础知识,数据结构
难度分级:P4 ,P5

9.简述一下java的异常体系,什么是受检异常,什么是运行时异常;封装一个API的时候什么情况下抛出异常。
参考答案:
java的异常体系:
在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
Throwable 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
Exception(异常)是应用程序中可能的可预测、可恢复问题。一般大多数异常表示中度到轻度的问题。异常一般是在特定环境下产生的,通常出现在代码的特定方法和操作中。在 EchoInput 类中,当试图调用 readLine 方法时,可能出现 IOException 异常。
Error(错误)表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。

受检异常:
可检测异常经编译器验证,对于声明抛出异常的任何方法,编译器将强制执行处理或声明规则,例如:sqlExecption 这个异常就是一个检测异常。你连接 JDBC 时,不捕捉这个异常,编译器就通不过,不允许编译。
非检测异常:
非检测异常不遵循处理或声明规则。在产生此类异常时,不一定非要采取任何适当操作,编译器不会检查是否已解决了这样一个异常。例如:一个数组为 3 个长度,=E5__你使用下标为3时,就会产生数组下标越界异常。这个异常 JVM 不会进行检测,要靠程序员来判断。有两个主要类定义非检测异常:RuntimeException 和 Error。
Error 子类属于非检测异常,因为无法预知它们的产生时间。若 Java 应用程序内存不足,则随时可能出现 OutOfMemoryError;起因一般不是应用程序的特殊调用,而是 JVM 自身的问题。另外,Error 一般表示应用程序无法解决的严重问题。
RuntimeException 类也属于非检测异常,因为普通 JVM 操作引发的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在 Java 应用程序中会频繁出现。因此,它们不受编译器检查与处理或声明规则的限制。
封装一个API的时候什么情况下抛出异常
如果调用方可以从异常中采取措施进行恢复的,就使用checked exception,如果客户什么也做不了,就用unchecked exception。这里的措施指的是,不仅仅是记录异常,还要采取措施来恢复。
解题思路:基础知识
考察点:java基础知识
难度分级:P4

9、string常量池的考核
参考答案: http://blog.sina.com.cn/s/blog_5203f6ce0100tiux.html
解题思路:基础知识
考察点:String
难度分级:P4,P5

10、在项目中用到了哪些java面向对象的特性,跟面向过程有什么不同?
参考答案:
这个属于开放性试题,主要考察面试者是否对面向对象有清晰的认识,一般来说会围绕着“继承”、“封装”、“多态”面向对象三大特征来描述;比如做了相同流程下不同特征数据的异构;比如抽象的定时任务模板,缓存模板,监听者模板等等。
解题思路:基础知识
考察点:面向对象
分类:面向对象 {校招,社招}
难度分级:P4,P5

11、是否发现过jdk的bug或者踩过jdk的一些坑 ?
参考答案:
一般很少有面试者能发现jdk的bug,但是踩坑的不是少数,主要看看面试者有没有总结,java的api用的多不多,理解的到不到位。这个没有参考答案,比如java中sublist的陷阱等等
解题思路:基础知识
考察点:面向对象
分类:面向对象 {校招,社招}
难度分级:P4,P5

JAVA Util

12、Hash冲突,有哪几种常见的解决方法,Java中HashMap用的是哪一种?
参考答案:
(1)开放定址法;
(2)拉链法;http://www.cnblogs.com/jillzhang/archive/2006/11/03/548671.html
Java中HashMap使用的是拉链法。
解题思路:基础知识
考察点:Hash冲突,HashMap的底层数据结构实现
分类:数据结构,Java集合框架
难度分级:P4

13、Java HashMap,已知整个生命周期内不会放入超过100个元素,那么占用内存大小最优且设置完初始值后无需自动扩容,该初始值应该设置为多少?
参考答案:
如果默认使用H ashMap内置的负载因子loadFactor为0.75。鉴于HashMap初始化设置大小为2的n次方,则100/0.75=133. 大于133的最小2的n次方为256个。
解题思路:基础知识
考察点: 考察HashMap的负载因子以及构造函数的理解
分类:Java集合框架{校招,社招}
难度分级:P4

14、Java HashMap在高并发情况下不当使用,可能会导致什么样极端情况,为什么?
参考答案:
在并发的多线程使用场景中,在resize扩容的时候,使得HashMap形成环链,造成死循环,CPU飙升至100%。可以举例子说明。
参考链接:http://wiki.sankuai.com/x/oUl9BQ
解题思路:
考察点:HashMap的并发性
分类:{校招,社招}
难度分级:P4,P5

15、HashMap/ConcurrentHashMap的数据结构实现,扩容机制,HashMap hash的冲突处理。
参考答案:
答案参考前面。
补充:扩容机制考察扩容时机,扩容容量变化机制,扩容具体实现步骤-源码resize() 函数。
解题思路:
考察点:HashMap/ConcurrentHashMap的底层实现
分类:{校招,社招}
难度分级:P4,P5

16、LinkedHashMap 数据结构实现
参考答案:
首先搞清楚HashMap得实现;然后重点考察和HashMap的区别。
LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。最好画个图解释下。Entry对象在HashMap的时候包含key,value,hash值,以及一个next;而在LinkedHashMap中新增了before和after。
解题思路:基础知识
考察点:HashMap和LinkedHashMap 的数据结构的区别
分类:{校招,社招}
难度分级:P4,P5

17、ArrayList和LinkedList的区别,数据结构实现,扩容机制
参考答案:
(1) ArrayList是实现了基于动态数组的数据结构,LinkedList基于双向循环链表的数据结构。
(2) 对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
(3) 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
(4) 查找操作indexOf,lastIndexOf,contains等,两者差不多。
(5) 随机查找指定节点的操作get,ArrayList速度要快于LinkedList.
当操作是在一列数据的后面添加数据而不是在前面或中间,并且需要随机地访问其中的元素时,使用ArrayList会提供比较好的性能;当你的操作是在一列数据的前面或中间添加或删除数据,并且按照顺序访问其中的元素时,就应该使用LinkedList了。
扩容: 针对ArrayList,在新增的时候,容量不够就需要扩容,2倍。
解题思路:基础知识
考察点:ArrayList和LinkedList的区别,ArrayList的扩容
分类:{校招,社招}
难度分级:P4

18、哈希函数的构造方法常见的有哪几种?
参考答案:
(1)直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a·key + b为散列函数。若其中H(key)中已经有值了,就往下一个找,直到H(key)中没有值了,就放进去。
(2) 数字分析法:就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。
(3)平方取中法:取关键字平方后的中间几位作为散列地址。
(4) 折叠法:将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址。
(5)随机数法:选择一随机函数,取关键字的随机值作为散列地址,通常用于关键字长度不同的场合。
(6)除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p,p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生同义词。
解题思路:基础知识
考察点:哈希函数的构造方法
分类:数据结构
难度分级:P4

19、HashMap的实现原理(内部数据结构,null key,rehash);为什么说hashMap不是线程安全的。
参考答案:
(1)内部数据结构实现:数组+链表 (最好画个图能解释清楚)
(2)key值不能重复,只能put一个key为null的键值对。可以更深层次考察对put(null,value)以及get(null)的 理解。
(3)HashMap在put时,经过了两次hash,一个是JDK自带的对对象key的hash,然后再对结果使用HashMap内部函数hash(int h);hash(int h)方法根据key的hashCode重新计算一次散列。可以更深入考察对hash(int h)以及indexFor(int h, int length)两个函数的理解。
(4)在put时如果空间不够就需要扩容resize(),考察扩容过程--重新计算复制。
(5)在并发的多线程使用场景中,使用HashMap形成环链,造成死循环,CPU飙升至100%。例子见链接。
http://wiki.sankuai.com/pages/viewpage.action?pageId=89609604
解题思路:基础知识
考察点: 考察HashMap的底层实现远离
分类:Java集合框架{校招,社招}
难度分级:P4

20、List有哪些实现,实现原理,如何选择实现;是否比较过性能差异?contains方法是怎么比较对象的?
参考答案:
(1)List的直接实现是两个抽象类,AbstactList和AbstractSequentialList.其中,AbstractList为随即访问(如数组)实现方案提供尽可能的封装,AbstractSequentialList为连续访问(如链表)实现方案提供了尽可能的封装。ArrayList,直接父类是AbstractList,数据结构是大小可变的数组,它不是同步的。LinkedList,直接父类是AbstractSquentialList,数据结构是双向链表,它不是同步的,它同时实现了Deque(双向队列)和Queue(队列)接口。同时它还提供了push和pop这两个堆栈操作的接口。Vector,直接父类是AbstractList,特性和ArrayList一样,只是它是线程同步的。Stack,直接父类是Vector,_=9E现堆栈这种数据结构。
(2)通过对象的equals方法。
解题思路:基础知识
考察点:考察对List的理解和运用以及equals的理解
分类:Java集合框架{校招,社招}
难度分级:P4

21、如何拷贝数组,怎样效率最高?为什么?
参考答案:
(1)使用循环结构 这种方法最灵活。唯一不足的地方可能就是代码较多
(2)使用Object类的clone()方法, 这种方法最简单,得到原数组的一个副本。灵活形也最差。效率最差,尤其是在数组元素很大或者复制对象数组时。
(3) 使用Systems的arraycopy这种方法被告之速度最快,并且灵活性也较好,可以指定原数组名称、以及元素的开始位置、复
制的元素的个数,目标数组名称、目标数组的位置。
浅拷贝和深拷贝得理解:定义一个数组int[] a={3,1,4,2,5}; int[] b=a; 数组b只是对数组a的又一个引用,即浅拷贝。
如果改变数组b中元素的值,其实是改变了数组a的元素的值,要实现深度复制,可以用clone或者System.arrayCopy
clone和System.arrayCopy都是对一维数组的深度复制;因为java中没有二维数组的概念,只有数组的数组。所以二维数组a中存储的实际上是两个一维数组的引用。当调用clone函数时,是对这两个引用进行了复制。
解题思路:基础知识
考察点:数组拷贝,浅拷贝和深拷贝的区别
分类:{校招,社招}
难度分级:P4,P5

七、其他

1.性格上的缺点
2.如何设计美国应该有多少个加油站

猜你喜欢

转载自blog.csdn.net/baidu_34794435/article/details/81558994