高级面试题 非常 有用
1,抽象类和接口的区别:
回答完概念后,我举了适配器和装饰器模式例子。适配器是把一个对象的接口转换供另一个接口调用,比如io读写的字符流通过适配器调用字节流对象来完成。
装饰器模式是接口不变,把一个抽象父类的功能增强,比如文件io流就是实现了io流抽象对象,调用文件读写的io优化,增强了io功能。
最后我举了自己项目中做C语言做USB转串口的适配器模式。
2,讲讲单例模式:
回答完概念后,我讲了饿汉和懒汉单例的实现,spring的默认单例运行。然后罗列一堆开源项目使用的单例+线程池。
最后讲了自己项目中使用的单例。还讲了适用范围的,此处单例仅适用于程序内部,系统中程序只允许启动一个实例的单例实现。
数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
7. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
计数器一般也是单例的.
3,讲讲string在内存的存储:
答完string和一般值类型如int、double的不同,存储在JVM的堆上,在栈上保存对象的引用。然后快速介绍jvm的GC算法。
最后讲了在代码中如何避免内存泄露。
4,cookie和session的优缺点: 有用
回答完标准答案后,我讲了一些自己项目中session共享的实现,快速画简要建构图,然后简单说了一下nginx反向代理配置tomcat集群,tomcat里配置session由某个开源插件来实现,session的产生由redis服务器来完成。
面试官刚好也研究过,问我单点登录怎么解决,我session共享关键问题解决后,只需要加台用户中心服务器即可。
实际上单点登录我并没有完全实现,但这堆应付面试是无伤大雅的。真要实现单点登录环境,相信给一周时间也能做出demo。
这时发现一个细节,面试官手里的纸上写了一些我说过的技术点,在设计模式和内存管理后面又加了一个单点登录。
二、进阶问题
5,讲讲多线程
我直接把《多线程编程核心》书里的知识点快速介绍一遍,然后说了一下多线程实现生产者-消费者的伪代码。
讲了MQ消息队列的点对点模式类似实现,引申出了MQ消息队列的发布订阅模式。这回有点表现过头了,说到一些公平锁和线程调度方面时,面试官有点发愣,我赶紧停下来等面试官问。
果然面试官可能有些不快地说,多线程你只是理论看得多,实际项目没有使用过吧?我赶紧说不好意思,我说到自己擅长领域就忘记了环境(当然我确实也没有游戏编程那种多线程经验)。
面试官态度变好了,我便拿那个专利项目举例,说多线程除了异步等待耗时操作外,也可以用在纯计算耗CPU的场景,有几个CPU核心开几个线程把CPU全占满,以加快计算。
多线程被顺利加入清单。
6,前面提到了MQ消息队列,那么你对分布式有什么经验?
我坦言分布式只是最近我在学习的,画了个简图,简单讲了下dubbo、zookeper、activiedMQ、redis、FastDFS组成的分布式架构。
分布式有所了解这个技能又被加入清单。
7,讲讲你项目架构中的性能优化
状态越来越好,性能优化我准备多时早就饥渴难耐了,这里的纲要按照 架构设计思维导图 来讲。
分前台,后台,数据库优化三大方面来展开。
最后结合了我写代码的规范标准,自己总结的不比大公司人多力量大,作为单打独斗的野生程序员能做到这个地步也差不多了.
8,我们数据安全性很高,讲讲你的安全设计
我讲了下自己登陆体系使用过的技术,密码MD5,RSA加密用户输入数据,AES解密数据库连接等。
中规中矩吧。
9,讲讲springMVC原理,及如何注入的
非基础方面可能问不出什么了,于是搞面试官冷不丁抛出一个基础问题。我的思路一时无法从系统架构的状态上切换过来,想了10秒也想不起。
在面试官引导下,我说了通过包扫描来注入。面试官说很正常,他也经常忘记一些基本的东西。
10,final,finally,finalize的区别?
基础关键字,如果这个答错应该是会被扣分的(其中finalize方法是在垃圾收集器删除对象之前调用的)。
当然基础知识我怎么可能忘记,顺便发说了一下service中一般不使用try catch finally,自己处理的话,配置的事务处理就不起作用了。
三、杀手问题
11,看你的项目经历,是开发企业应用居多,没有互联网和电商项目经验。现在我问你如果是电商项目,你如果拆分成分布式项目。
这个问题直击弱点,这里其实已经不是考察能力是否匹配职位需求了,应该是为优中选优准备的附加题。
我答不上来,就说了下我对自己项目分布式拆分的思考,因为我从搭建自己项目那天开始就想着给企业所有几万用户使用,腹稿早就有了。
然后推理电商项目中用户、支付、交易记录这些也注册为基础服务。利用分布式缓存提高性能,分布式文件系统来存储海量数据。
500强企业的专家级面试果然是变态,当时我不知道分布式数据库这个概念,导致后面被针对海量数据和分布式数据库攻击。
12,前面说到海量数据,你对海量数据有哪些了解?
杀手问题果然是连环陷阱,就看你能闯过多少关获得加分了。还好我每次回答都注意答案出现的相关概念都至少是自己了解过的,以防御针对弱点攻击。
我说海量数据加算法=大数据,讲了几个海量数据的典型算法, 提到海量数据算法又顺带讲了分布式最终一致性那个二次提交确认的算法。
说到面试官不了解的领域再次被打断了,面试官又问我下一个杀手问题。海量数据算法了解的标签被加上。
13,我们公司的的数据中心,经常会遇到短时间写入上百万数据场景,你会怎么处理?
答案应该是分布式数据库,前面没提到分布式数据库,这里再次被针对弱点提问,巧妙的隐藏概念,防止浑水摸鱼。
开始我说用MQ消息队列先消掉高并发峰值,向订票系统那样延后操作。面试官说要求实时处理,你这想法只是推迟。
我想了一下又说再加分布式缓存,面试说还是实时性不够。
我突然想到做单片机时,为了提高数据传输量,增加多几个IO口一起来传输。讲了到利用NIO的原理多增加端口来提高数据吞吐量。
一张大数量的表里,如何取出10条数据
面试官说:“你对高并发,缓存了解多少?”
。。。。。。
面试官说:“SQL Server用的熟练吗? 一张大数量的表里,如何取出10条数据。 ”
。。。。。。
面试官说:“你对Http协议了解的多吗?”
。。。。。。
面试官说:“你对FastDFS了解吗? ”
此时一般会问到一些Java的基础知识,比如
synchronized static修饰类和方法有什么区别
是同步 修饰类代表是一个同步类,
HashMap的原理,底层数据结构,rehash的过程,指针碰撞问题
HashMap为什么线程不安全(hash碰撞与扩容导致)
HashMap的线程安全问题,为什么会产生这样的线程安全问题
ConcurrentHashMap的数据结构,底层原理,put和get是否线程安全
Java IO的一些内容,包括NIO,BIO等
1、面向流与面向缓冲
Java IO和NIO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。
2、阻塞与非阻塞IO
Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。
3、选择器(Selectors)
Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。
3.1.2 Java高级特性
此时问到的问题一般包含JVM,多线程的一些内容,这块建议大家多看看源码,大致如下:
Java线程池的构造方法,里面参数的含义,以及原理
volatile和ThreadLocal解决了什么问题
CAS在Java中的具体实现
Java虚拟机的构成,以及一个Java对象的生命周期,还有堆栈和方法区中存储的内容
JVM的GC过程,包括一些实际问题的分析,比如说明一个现象,让你分析可能是什么原因会导致这样的问题,应该如何对JVM参数进行调优
synchronized和Lock的区别,以及底层实现原理
Full GC和Minor GC触发的条件
GC Roots的选择
jmap,jstat,jstack等的使用场景,MAT等
ClassLoader的加载过程
CountDownLatch、CyclicBarrier和Semaphore等
Java 8 的新特性等
3.1.3 数据库
这里的数据库包含两种,一种一般是MySQL,另外是NoSql数据库,包括Redis、MongoDB等。一般会问的问题有:
inner join和left join等的区别
SQL调优,explain,profile等
ACID
数据库的事务隔离级别,以及他们分别能解决什么问题
Redis的几种数据结构
Redis是单线程还是多线程
Redis的持久化
悲观锁和乐观锁的含义
最左前缀索引,索引的数据结构,聚簇索引等(这块还没搞明白)
3.1.4 框架
3.1.4.1 Spring
因为spring是我们常用的框架,所以这块的内容会问的比较多,也会比较细。
Spring的两大特性(IoC和AOP)
Spring的bean的生命周期
Spring是如何解决Bean的循环引用问题的
AOP的两种实现方式,以及两者的区别(这里其实使用了动态代理,具体动态代理分为两种,一种是JDK的动态代理,主要使用的是JDK的反射,还有一种是CGLib,两者区别可以自己搜索,文章比较多)
AOP一般的使用场景
Spring的事务原理
3.1.4.2 MyBatis
这块问到的比较简单些:
$和#的区别
MyBatis和Hibernate的区别
3.1.4.3 Dubbo
因为平时自己用到了Dubbo,所以这块会有问到:
RPC的原理
如前所述,RPC其实也是种C/S的编程模式,有点类似C/S Socket 编程模式,但要比它更高一层。
当我们在建立RPC服务以后,客户端的调用参数通过底层的RPC传输通道,可以是UDP,也可以是TCP,并根据传输前所提供的目的地址及RPC上层应用程序号转至相应的RPC应用程序服务端,且此时的客户端处于等待状态,直至收到应答或Time Out超时信号。当服务器端获得请求消息,则会根据注册RPC时告诉RPC系统的例程入口地址,执行相应的操作,并将结果返回至客户端。
当一次RPC调用结束后,相应线程发送相应的信号,客户端程序才会继续运行。
在这个过程中,一个远程过程是有三个要素来唯一确定的:程序号、版本号和过程号。
程序号是用来区别一组相关的并且具有唯一过程好的远程过程。一个程序可以有一个或几个不同的版本,而每个版本的程序都包含一系列能被远程调用的过程,通过版本的引入,使得不同版本下的RPC能同时提供服务。每个版本都包含有许多可供远程调用的过程,每个过程则有其唯一标示的过程号。
1)服务消费方(client)调用以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3)client stub找到服务地址,并将消息发送到服务端;
4)server stub收到消息后进行解码;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行并将结果返回给server stub;
7)server stub将返回结果打包成消息并发送至消费方;
8)client stub接收到消息,并进行解码;
9)服务消费方得到最终结果。
Dubbo是如何完成远程调用的
serviceName serverAddressList clientAddressList
UserService 192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.4 172.16.0.1,172.16.0.2
ProductService 192.168.0.3,192.168.0.4,192.168.0.5,192.168.0.6 172.16.0.2,172.16.0.3
OrderService 192.168.0.10,192.168.0.12,192.168.0.5,192.168.0.6 172.16.0.3,172.16.0.4
当某个Server不可用,那么就更新受影响的服务对应的serverAddressList,即把这个Server从serverAddressList中踢出去(从地址列表中删除),同时将推送serverAddressList给这些受影响的服务的clientAddressList里面的所有Client。如:192.168.0.3挂了,那么UserService和ProductService的serverAddressList都要把192.168.0.3删除掉,同时把新的列表告诉对应的Client 172.16.0.1,172.16.0.2,172.16.0.3;
当某个Client挂了,那么更新受影响的服务对应的clientAddressList
ConfigServer根据服务列表,就能提供一个web管理界面,来查看管理服务的提供者和使用者。
新加一个Server时,由于它会主动与ConfigServer取得联系,而ConfigServer又会将这个信息主动发送给Client,所以新加一个Server时,只需要启动Server,然后几秒钟内,Client就会使用上它提供的服务
Client
调用服务的机器,每个Client启动时,主动与ConfigServer建立Socket长连接,并将自己的IP等相应信息发送给ConfigServer。
Client在使用服务的时候根据服务名称去ConfigServer中获取服务提供者信息(这样ConfigServer就知道某个服务是当前哪几个Client在使用),Client拿到这些服务提供者信息后,与它们都建立连接,后面就可以直接调用服务了,当有多个服务提供者的时候,Client根据一定的规则来进行负载均衡,如轮询,随机,按权重等。
一旦Client使用的服务它对应的服务提供者有变化(服务提供者有新增,删除的情况),ConfigServer就会把最新的服务提供者列表推送给Client,Client就会依据最新的服务提供者列表重新建立连接,新增的提供者建立连接,删除的提供者丢弃连接
Server
真正提供服务的机器,每个Server启动时,主动与ConfigServer建立Scoket长连接,并将自己的IP,提供的服务名称,端口等信息直接发送给ConfigServer,ConfigServer就会收集到每个Server提供的服务的信息。
优点:
1,只要在Client和Server启动的时候,ConfigServer是好的,服务就可调用了,如果后面ConfigServer挂了,那只影响ConfigServer挂了以后服务提供者有变化,而Client还无法感知这一变化。
2,Client每次调用服务是不经过ConfigServer的,Client只是与它建立联系,从它那里获取提供服务者列表而已
3,调用服务-负载均衡:Client调用服务时,可以根据规则在多个服务提供者之间轮流调用服务。
4,服务提供者-容灾:某一个Server挂了,Client依然是可以正确的调用服务的,当前提是这个服务有至少2个服务提供者,Client能很快的感知到服务提供者的变化,并作出相应反应。
5,服务提供者-扩展:添加一个服务提供者很容易,而且Client会很快的感知到它的存在并使用它。
Dubbo如何进行调优
超时: 服务消费方, 访问服务提供方应该设置一个超时时间, 如果开发阶段, 在服务提供方设置debug,
进行调试, 会有一段时间不能返回结果, 这样会导致服务消费方报错. 所以超时时间应该尽可能设置的长一点.
直接连接: 在线上, 需要zookeeper来协调服务提供方, 因为服务提供方有可能是一个几百台机器的集群, 这样服务消费
方在调用提供方的时候就不知道服务提供方的机器的ip和端口, 所以需要zookeeper进行协调.
在本地开发阶段, 就一个服务提供方, 一个服务消费方, 不是集群, 所以将服务消费方直接连接到服务提供方
就可以, 这样可以省去一个虚拟机, 是本地开发机器性能提高.
服务消费方不检查服务提供方: 设置服务消费方在启动的时候不检查服务提供方有没有启动, 在使用的时候再去检查 ,
这样就可以无论先启动服务提供方还是消费方, 都可以.
Dubbo的通信协议
Dubbo RPC服务框架支持丰富的传输协议、序列化方式等通讯相关的配置和扩展。dubbo执行一次RPC请求的过程大致如下:消费者(Consumer)向注册中心(Registry)执行RPC请求,注册中心分配服务URL并路由到具体服务提供方(Provider),消费者和服务提供方建立网络连接,服务提供方在本地创建连接池对象并提供远程服务,对于长连接类型协议(如dubbo协议)将保持连接,减少握手认证,调用过程中可以避免频繁建立和断开连接导致的性能开销,保持长连接需要有心跳包的发送,所以对于非频繁调用的服务保持连接同样会有消耗。更多关于dubbo详细介绍请参照官方文档(http://alibaba.github.io/dubbo-doc-static/Home-zh.htm)。
1、支持常见的传输协议:RMI、Dubbo、Hessain、WebService、Http等,其中Dubbo和RMI协议基于TCP实现,Hessian和WebService基于HTTP实现。
2、传输框架:Netty、Mina、以及基于servlet等方式。
3、序列化方式:Hessian2、dubbo、JSON(fastjson 实现)、JAVA、SOAP 等。
本文主要基于dubbo框架下的通讯协议进行性能测试对比。
Dubbo是如何实现负载均衡的
默认的负载方式是随机负载均衡(@SPI(RandomLoadBalance.NAME)),我们也可以指定使用哪种负载均衡:
<dubbo:reference interface="xxx" loadbalance="roundrobin"/> 或 <dubbo:service interface="xxx" loadbalance="roundrobin" />
肯定有人会问,普通的随机负载均衡和轮询的负载均衡方式效果不是一样的吗?确实,如果是普通的随机,理论上来说和轮询的方式效果一致,甚至有时候还不如轮询的好,因为这和采取的随机数的随机程度和随机数生成开销两种因素有关,但如果在随机过程中加入权重这一属性的话,随机的优势不言而喻了,比如可以做到“预热”功能,给刚上的服务器在某段时间内分配比其他服务器更少的请求,让刚上的服务器能先“热热身”,这一点,普通轮询方式是很难做到的。没错,Dubbo默认的随机负载方式就加入了权重这一因数,权重精确到某个接口的某个方法,这也是我们所期望的,其默认“预热”时间是10分钟。
Dubbo中有个抽象类AbstractLoadBalance,它实现了获取某个接口某个方法的权重值,预热部分的计算也包含在其中,这里代码就不贴出来了,之所以Dubbo这样做,是因为其他负载形式都用到权重因子。
我们这里简单描述下各种负载均衡的实现方式:
随机负载均衡(RandomLoadBalance):先统计所有服务器上该接口方法的权重总和,然后对这个总和随机nextInt一下,看生成的随机数落到哪个段内,就调哪个服务器上的该服务。
轮询负载均衡(RoundRobinLoadBalance):如果所有服务器的该接口方法的权重一样,则直接内部的序列计数器(sequences)+1然后对服务器的数量进行取模来决定调用哪个服务器上的服务;如果服务器的该接口方法的权重不一样(就是说存在预热中的服务器),则找到其中最大的权重,然后将内部的权重计数器(weightSequences)+1并对该最大权重数取模,然后再找出权重比该取模后的值大服务器列表,最后通过内部的序列计数器(sequences)+1然后对服务器列表数量进行取模来决定调用哪个服务器上的服务。
最少活跃负载均衡(LeastActiveLoadBalance):每个接口和接口方法都对应一个RpcStatus对象,记录了他们的活跃数、失败数等等相关统计信息,此种负载均衡方式是在活跃数最低的服务器中对其权重的总和取模来看结果是在哪个权重段中,则选择该服务器来调用,活跃数就像并发量降级中的计数器一样,开始调用时活跃数+1,调用结束时活跃数-1,所以活跃值越大,表明该提供者服务器的该接口方法耗时越长,而消费能力强的提供者接口往往活跃值很低。最少活跃负载均衡保证了“慢”提供者能接收到更少的服务器调用。
一致哈希负载均衡(ConsistentHashLoadBalance):一致性哈希算法的负载均衡保证了同样的请求(参数)将会落到同一台服务器上,这在某些场景是非常有用的,Dubbo中默认采用了160个虚拟节点,因为Dubbo的请求URL中除了我们使用的参数,还有些额外的系统调用参数,比如timestamp、loadbalance、pid和application等,有人可定会问,Dubbo会对URL中哪些参数进行hash,Dubbo默认除了对我们接口所有参数进行hash外,还会加上这些额外参数,因为有timestamp,这是不是也意味着在Dubbo的重试调用时timestamp不变?
上述的四种负载均衡,除了一致性哈希,其他三种都依赖了接口方法的权重统计,借助权重的不同,随机负载均衡就能做到动态调整的效果,Dubbo中的轮询负载方式,也利用了权重,那么有人会问,Dubbo中的随机和轮询是不是差别不大?是的,笔者也这样认为,相似的效果,也有着相似的缺点,Dubbo中的随机和轮询负载都没有考虑到提供者服务器消费服务的能力,如果相差很大,“慢”提供者有可能被“快”提供给者给拖垮,其根本原因也是这两种负载均衡的加权因子考虑的不是服务耗时。最少活跃的负载均衡就很巧妙的解决了此问题,而且它不是直接通过统计服务调用的耗时,而是采用统计调用差(活跃数)。一致性哈希特别适用于有缓存的系统,这样缓存命中率会比较高。
可以自行扩展负载均衡策略,参见:负载均衡扩展
Random LoadBalance
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
权重加倍
RoundRobin LoadBalance
轮循,按公约后的权重设置轮循比率。
存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
解决办法 :结合权重,把第二台机(性能低的)的权重设置低一点
LeastActive LoadBalance
最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
ConsistentHash LoadBalance
一致性Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing。
缺省只对第一个参数Hash,如果要修改,请配置<dubbo:parameter key="hash.arguments" value="0,1" />
缺省用160份虚拟节点,如果要修改,请配置<dubbo:parameter key="hash.nodes" value="320" />
Dubbo管理台配置负载均衡
权重调节
配置如:
<dubbo:serviceinterface="..."loadbalance="roundrobin"/>
或:
<dubbo:referenceinterface="..."loadbalance="roundrobin"/>
或:
<dubbo:serviceinterface="...">
<dubbo:methodname="..."loadbalance="roundrobin"/>
</dubbo:service>
一般在实际项目我们配置权重或负载均衡时不在代码中写死,我们动态使用默认配置,需要调节时通过dubbo管控台上进行配置
或:
<dubbo:referenceinterface="...">
<dubbo:methodname="..."loadbalance="roundrobin"/>
</dubbo:reference>
3.1.4.4 ZooKeeper
ZK的使用场景
ZK的选举机制
ZK的节点类型
一致性Hash原理
3.1.5 数据结构和算法
这块的内容是基础,如果面试官怀疑你的能力,一般一会问到这部分内容,比如树的遍历、快速排序等。
3.1.6 linux
一般会问一些命令的使用,然后会举一个实际的场景,让你用命令去排查问题,这块自己不是很熟,需要尽快加强。
3.1.7 综合题
这块的题目,面试官一般会问的比较深入。比如如何设计一个抢购系统,String转Integer等,这部分需要考验的就是一个人的临场应变能力,以及在平时工作中系统设计能力的积累,以及考虑问题是否周到等。也有可能会对你简历上面写的系统的设计进行详细的询问,所以在你写简历的时候,千万不能把自己不熟悉的内容写上去,而且自己又讲不清,这样一般会被直接pass掉。
当然也会问一些常用的maven的命令,设计模式的题目(这部分问的比较多的就是单例模式)。
1、 JAVA基础
1) 抽象类和接口的区别?
补充问题:JAVA8中为什么要加入默认方法?
2) 静态内部类(static class)的作用?
3) 序列化和反序列化
4) 动态代理和静态代理的区别?
赠送问题:代理模式,什么是代理模式?如何实现?代理模式结构图是怎样的?代理模式应用在什么场景?
5) nio熟悉吗,nio和io的区别?
6) java8有哪些新特性?
2、 Java API
1) transient关键字的作用?
2) volatile关键字的作用?
3) abstract和final是否可同时使用?
4) ArrayList、LinkedList、vector的区别?
5) HashMap、LinkedHashMap,concurrentHashMap的区别,concurrentHashMap为什么特别好用,你看过源码吗?
6) collection的继承结构,你是否看过源码?
3、 JVM调优(性能)
1) 有哪些调优工具
2) 如何快速定位有问题代码
3) 内存溢出如何处理,如何调优
4) 垃圾回收机制,有哪些垃圾回收算法,如何配置垃圾回收策略
5) 新生代和老年代
4、 Tomcat
tomcat可以稳定支持的最大并发用户数
Tomcat集群如何架设:Tomcat+Apache
集群时特别关注两个问题:
1:如何实现多应用服务器间的session共享:(一台服务器崩溃,另外一台服务器可以继续支持)
2:如何分发请求到各个应用服务器实现压力分解:(这里的解决方案是用apache做 web服务器)
算法问题
1、 生产者和消费者问题?
2、 查找算法有几种,写出实现代码?
3、 排序算法有几种,写出实现代码?
4、 遍历二叉树,分别按照前序、中序、后续?
5、 红黑树
程序题
1、 写出一个字符串,打印出字符串中字符的所有排序
2、 无序的有重复数据的list变成有序的无重复数据的list
框架篇
1、 spring核心:
分别说说aop和IOC
事务配置的几种方式?
spring有几种注入方式?
spring依赖注入的四种装配方式?
spring的几个重要注解@Component(不推荐使用)、@Repository、@Service、@Controller
2、 SpringMVC和Struts2:两者的区别
3、 Mybatis和hibernate:两者的区别
mybatis如何实现多表关联查询
mybatis的resultMap
mybatis的#和$
4、 是否可以用maven搭建项目,maven如何构建web项目?
5、 Git的使用
6、 当日志非常大时,如何查找需要的日志?
7、 SSH的局限有哪些
数据库篇
数据库基础
1、 MySQL和Oracle的区别
mysql可以设置主键自增策略 oracle 是通过序列来主键自增
五、提交方式
oracle默认事务不自动提交,需要用户手动提交。
mysql默认是自动提交。
mysql默认 读已提交 oracle 串行化
mysql:
mysql以表级锁为主,对资源锁定的粒度很大,如果一个session对一个表加锁时间过长,会让其他session无法更新此表中的数据。
虽然InnoDB引擎的表可以用行级锁,但这个行级锁的机制依赖于表的索引,如果表没有索引,或者sql语句没有使用索引,那么仍然使用表级锁。
2、 oracle移植到mysql需要处理哪些
3、 存储过程
体现在:
1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般 SQL 语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
2.当对数据库进行复杂操作时(如对多个表进行 Update,Insert,Query,Delete 时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。这些操作,如果用程序来完成,就变成了一条条的 SQL 语句,可能要多次连接数据库。而换成存储,只需要连接一次数据库就可以了。
3.存储过程可以重复使用,可减少数据库开发人员的工作量。
4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权。
4、 mysql存储引擎innodb和myisam的区别
MyISAM、InnoDB区别 引擎
l MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。
l MyISAM表不支持外键,InnoDB支持
l MyISAM锁的粒度是表级,而InnoDB支持行级锁定。
l MyISAM支持全文类型索引,而InnoDB不支持全文索引。(mysql 5.6后innodb支持全文索引)
MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。当你的数据库有大量的写入、更新操作而查询比较少或者数据完整性要求比较高的时
候就选择innodb表。当你的数据库主要以查询为主,相比较而言更新和写 入比较少,并且业务方面数据完整性要求不那么严格,就选择mysiam表。
、一张表,里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把Mysql重启,再insert一条记录,这条记录的ID是18还是15 ?(区分两种数据库引擎)
(1)如果表的类型是MyISAM,那么是18。
因为MyISAM表会把自增主键的最大ID记录到数据文件里,重启MySQL自增主键的最大ID也不会丢失。 数据和索引单独的文件
(2)如果表的类型是InnoDB,那么是15。
InnoDB表只是把自增主键的最大ID记录到内存中,所以重启数据库或者是对表进行OPTIMIZE操作,都会导致最大ID丢失。 因为数据和索引同一个文件
数据库优化
1、 sql优化
2、 索引
关于索引:联合索引A和B,当按照A、A和B、B查询时索引使用情况?
3、 数据库优化,使用过哪些优化工具:常用的SQLYOG、基准测试,expain、status等
具体问题:
如何找到并定位慢SQL?
如何确定表和查询是否是最优的?
枚举类型如何使用,枚举类型的误用带来的损失?
有没有什么工具可以监控数据库,快速查看有问题的sql?如果存在大批量有问题的sql,如何排查?
如何诊断响应差的(太多线程),僵尸进程(无响应或长时间运行),或者诊断连接问题?
如果在某段时间内用户反映服务器变慢,如何知道服务器性能差?
假设已经检查了所有常规信息——内存、磁盘等,而所有这些信息都在正常范围内,没有出现错误和异常,这时,你怎么知道系统是否运行变慢?
数据库进阶
1、 当数据库存储数据出现瓶颈,如何处理?——数据库水平拆分、垂直拆分
2、 说说水平拆分和垂直拆分,什么时候水平拆分,什么时候垂直拆分,分别解决了哪些问题,分别存在哪些不能解决的问题,如何结合使用?
3、 当水平拆分时,到不同的表和库中或不同的分布式服务器上时:不同的表可以联合查询(union)、不同的库可以加上库名进行联合查询;如果需要查询的数据分布在不同的服务器之间,如何查询?如何在存储数据时就将需要同时查询的数据放在同一服务器上(存储时取模或者按照时间分布数据,查询的时候取模或者按照时间查询)
4、 mysql读写分离
5、 数据库集群
升级篇
分布式
1、 有哪些分布式框架,对比其性能优劣?
同步调用:RSET(JAX-RS、Spring Boot)、RPC(Thrift、Dubbo、HSF)
异步调用:Kafka、Notify、MetaQ
同步和异步的区别,分别用于什么场景?
2、 dubbo + zookeeper
3、 nosql(Redis、memcache、MongoDB)
大并发的处理
1、 负载均衡
2、 分布式
3、 缓存
4、 数据库分库分表
5、 数据库集群
6、 图片服务器分离
7、 首页静态化
大数据问题:
假如每天产生5亿行日志文件,如何搜索到指定内容?
有一个100T大小的文件存放在磁盘中,不借助任何外部存储设备,如何统计指定字符串的个数?
同上,有一个文件,存放每天访问的URL,每天有100万条,如何统计URL的个数?
测试1000万条数据的查询
多线程
1、 有哪些多线程的应用场景
举一个小栗子:
一个文本文件有100M,全是字符串,我要执行切分字符串,每达到N长度便执行切腹,最后求切分完成的字符串的集合
单线程处理:读取文本文件数据,扫描全部数据,一个一个的切分,最后消耗时间=文件传输时间(文本数据加载到内存)+切分过程消耗
多线程处理:
专门设置一个线程执行加载数据的操作,此时,如果加载的数据达到一个设定值,启动一个切线程处理,如此继续,多个切分字符串的线程能够并发执行,CPU的利用率提高了(文件传输的过程中没有占用处理器,而可以将加载的部分数据分配给切分线程,占用处理器来执行任务)
总结:
单线程处理,文件加载的过程中,处理器一直空闲,但也被加入到总执行时间之内,串行执行切分总时间,等于每切分一个时间*切分后字符串的个数,执行程序,估计等几分钟能处理完就不错了
多线程处理,文件加载过程与拆分过程,拆分过程与拆分过程,都存在并发——文件加载的过程中就执行了切分任务,切分任务执行过程中多线程并行处理,总消耗时间能比单线程提高很多,甚至几个数量级都不止。
2、 你自己有写过多线程吗,在哪些场景
3、 线程池,java提供的线程池有哪几种?
4、 队列
5、 servlet是线程安全的吗,如何改进?
不是
6、 实现同步的几种方式?
安全
关于安全方面做了哪些工作?
用shiro框架对权限进行校验, 密码通过md5进行加密
手机、支付如何保证信息安全?
sql注入问题
如何保证访问URL安全:如何不暴露真实的URL地址;如何防止篡改URL地址;如何防止在URL中SQL注入?
设计模式
1、 你熟悉哪些设计模式
2、 框架中用到哪些设计模式
java IO:装饰器模式(Decorator)、适配器模式(Adapt)
Spring :访问者模式(Visitor)、代理模式(Proxy)、策略模式(Strategy)
SpringMVC:模版模式(TempleteMethod) JDBCTemplete 模板模式 省去了在代码中try catch finally
Mybatis: 简单工厂模式、工厂方法模式(FactoryMethod)、抽象工厂模式(Abstract Factory)
Tomcat:门面模式、观察者模式(Observer)、命令模式(Command)、责任链模式(chainof responsible)
Velocity :合成模式
3、 装饰模式和适配器模式的区别
适配器模式 一个接口适配到另一个接口 形成一个新接口 例如字节流到字符流的转换
装饰模式 装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口 例如 FileInpustream 实现Inpustream接口 BuffereInpustream 实现 Inpustream BuffereInpustream对 FileInpustream进行增强
4、 写一个单例模式
Linux
1、 会使用哪些命令
查看端口是否被占用
netstat -anp |grep 3306
如何查看指定的日志
1、tail -f filename 说明:监视filename文件的尾部内容(默认10行,相当于增加参数 -n 10),刷新显示在屏幕上。退出,按下CTRL+C。 2、tail -n 20 filename 说明:显示filename最后20行。
网络
1、 通信协议是否有了解,TCP/UDP等、HTTP
2、 http反向代理
业务篇
1、 订单:大量并发问题
1.使用缓存:使用程序直接保存到内存中。或者使用缓存框架: 用一个特定的类型值来保存,以区别空数据和未缓存的两种状态。
2.数据库优化:表结构优化;SQL语句优化,语法优化和处理逻辑优化;分区;分表;索引优化;使用存储过程代替直接操作。
3.分离活跃数据:可以分为活跃用户和不活跃用户。
4.批量读取和延迟修改: 高并发情况可以将多个查询请求合并到一个。高并发且频繁修改的可以暂存缓存中。
5.读写分离: 数据库服务器配置多个,配置主从数据库。写用主数据库,读用从数据库。
6.分布式数据库: 将不同的表存放到不同的数据库中,然后再放到不同的服务器中。
2、 订单或产品数据量变大之后如何优化
在接口提交订单过来后,把订单写数据库后,同时把订单写入消息队列msmq,然后N台VPS通过外网实时轮询这台msmq,取订单,处理订单,再直连数据库修改订单状态。此方案可以减少数据库访问与连接数,同时不用对数据库加锁询。
3、 交易付款如何操作
4、 与物流接口
5、 画出你负责的项目的架构图