近期大厂面试题总结
Posted 编程指南针
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了近期大厂面试题总结相关的知识,希望对你有一定的参考价值。
就业指导需要扩充的知识点
数据库死锁
产生死锁的原因主要是:
(1)系统资源不足。
(2)进程运行推进的顺序不合适。
(3)资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。
**死锁的预防和解除: **
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确定资源的合理分配算法,避免进程永久占据系统资源。此外,也要防止进程在处于等待状态的情况下占用资源,在系统运行过程中,对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配 。因此,对资源的分配要给予合理的规划。
如何将死锁减至最少
虽然不能完全避免死锁,但可以使死锁的数量减至最少。将死锁减至最少可以增加事务的吞吐量并减少系统开销,因为只有很少的事务回滚,而回滚会取消事务执行的所有工作。由于死锁时回滚而由应用程序重新提交。
下列方法有助于最大限度地降低死锁:
(1)按同一顺序访问对象。
(2)避免事务中的用户交互。
(3)保持事务简短并在一个批处理中。
(4)使用低隔离级别。
(5)使用绑定连接。
常见的设计模式
工厂、单例、包装、代理、模板
spring中的设计模式
第一种:简单工厂
又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一。
简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类。
spring中的BeanFactory就是简单工厂模式的体现,根据传入一个唯一的标识来获得bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。如下配置,就是在 HelloItxxz 类中创建一个 itxxzBean。
<bean id="singletonBean" class="com.itxxz.HelloItxxz">
<constructor-arg>
<value>Hello! 这是singletonBean!value>
</constructor-arg>
</ bean>
<bean id="itxxzBean" class="com.itxxz.HelloItxxz"
singleton="false">
<constructor-arg>
<value>Hello! 这是itxxzBean! value>
</constructor-arg>
</bean>
</beans>
第二种:工厂方法(Factory Method)
通常由应用程序直接使用new创建新的对象,为了将对象的创建和使用相分离,采用工厂模式,即应用程序将对象的创建及初始化职责交给工厂对象。
一般情况下,应用程序有自己的工厂对象来创建bean.如果将应用程序自己的工厂对象交给Spring管理,那么Spring管理的就不是普通的bean,而是工厂Bean。
螃蟹就以工厂方法中的静态方法为例讲解一下:
public class StaticFactoryBean
public static Integer createRandom()
return new Integer(new Random().nextInt());
建一个config.xm配置文件,将其纳入Spring容器来管理,需要通过factory-method指定静态方法名称
class="example.chapter3.StaticFactoryBean" factory-method="createRandom" //createRandom方法必须是static的,才能找到 scope="prototype"
/>
测试:
public static void main(String[] args)
//调用getBean()时,返回随机数.如果没有指定factory-method,会返回StaticFactoryBean的实例,即返回工厂Bean的实例
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("config.xml"));
System.out.println("我是IT学习者创建的实例:"+factory.getBean("random").toString());
第三种:单例模式(Singleton)
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
spring中的单例模式完成了后半句话,即提供了全局的访问点BeanFactory。但没有从构造器级别去控制单例,这是因为spring管理的是是任意的java对象。
核心提示点:Spring下默认的bean均为singleton的,可以更改scope=“protype”
第四种:适配器(Adapter)
在Spring的Aop中,使用的Advice(通知)来增强被代理类的功能。Spring实现这一AOP功能的原理就使用代理模式(1、JDK动态代理。2、CGLib字节码生成技术代理。)对类进行方法级别的切面增强,即,生成被代理类的代理类, 并在代理类的方法前,设置拦截器,通过执行拦截器重的内容增强了代理方法的功能,实现的面向切面编程。
Adapter类接口:Target
boolean supportsAdvice(Advice advice);
MethodInterceptor getInterceptor(Advisor advisor);
MethodBeforeAdviceAdapter类,Adapter
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable
public boolean supportsAdvice(Advice advice)
return (advice instanceof MethodBeforeAdvice);
public MethodInterceptor getInterceptor(Advisor advisor)
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
第五种:包装器(Decorator)
在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在spring和hibernate框架中总是配置一个数据源,因而sessionFactory的dataSource属性总是指向这个数据源并且恒定不变,所有DAO在使用sessionFactory的时候都是通过这个数据源访问数据库。但是现在,由于项目的需要,我们的DAO在访问sessionFactory的时候都不得不在多个数据源中不断切换,问题就出现了:如何让sessionFactory在执行数据持久化的时候,根据客户的需求能够动态切换不同的数据源?我们能不能在spring的框架下通过少量修改得到解决?是否有什么设计模式可以利用呢?
首先想到在spring的applicationContext中配置所有的dataSource。这些dataSource可能是各种不同类型的,比如不同的数据库:Oracle、SQL Server、mysql等,也可能是不同的数据源:比如apache 提供的org.apache.commons.dbcp.BasicDataSource、spring提供的org.springframework.jndi.JndiObjectFactoryBean等。然后sessionFactory根据客户的每次请求,将dataSource属性设置成不同的数据源,以到达切换数据源的目的。
spring中用到的包装器模式在类名上有两种表现:一种是类名中含有Wrapper,另一种是类名中含有Decorator。基本上都是动态地给一个对象添加一些额外的职责。
第六种:代理(Proxy)
为其他对象提供一种代理以控制对这个对象的访问。 从结构上来看和Decorator模式类似,但Proxy是控制,更像是一种对功能的限制,而Decorator是增加职责。
spring的Proxy模式在aop中有体现,比如JdkDynamicAopProxy和Cglib2AopProxy。
第七种:观察者(Observer)
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
spring中Observer模式常用的地方是listener的实现。如ApplicationListener。
第八种:策略(Strategy)
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
spring中在实例化对象的时候用到Strategy模式
在SimpleInstantiationStrategy中有如下代码说明了策略模式的使用情况:
第九种:模板方法(Template Method)
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
Template Method模式一般是需要继承的。这里想要探讨另一种对Template Method的理解。spring中的JdbcTemplate,在用这个类时并不想去继承这个类,因为这个类的方法太多,但是我们还是想用到JdbcTemplate已有的稳定的、公用的数据库连接,那么我们怎么办呢?我们可以把变化的东西抽出来作为一个参数传入JdbcTemplate的方法中。但是变化的东西是一段代码,而且这段代码会用到JdbcTemplate中的变量。怎么办?那我们就用回调对象吧。在这个回调对象中定义一个操纵JdbcTemplate中变量的方法,我们去实现这个方法,就把变化的东西集中到这里了。然后我们再传入这个回调对象到JdbcTemplate,从而完成了调用。这可能是Template Method不需要继承的另一种实现方式吧。
以下是一个具体的例子:
JdbcTemplate中的execute方法
加密
- 敏感信息加密 (如:密码)
-
敏感信息单独建立数据库并控制权限(如:身份证信息,电话)
数据库安全
防止sql注入
使用预编译sql,避免使用拼接sql
避免提供让调用者直接传入sql语句的方法
java常用的加密解密方法
双向加密
1. 对称加密
采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。需要对加密和解密使用相同密钥的加密算法。由于其速度,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。
常用的对称加密算法
- DES算法
- 3DES算法
-
AES算法
-
非对称加密
与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥 。公开密钥与私有密钥是一对,如果用公开密钥对数据
进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的
密钥,所以这种算法叫作非对称加密算法。
常用的非对称加密算法
- RSA 公钥加密算法
- DSA算法
**单向加密(信息摘要) **
MD5、SHA、HMAC这三种加密算法,可谓是非可逆加密,就是不可解密的加密方法,我们称之为单向加密算法。
MD5 -- message-digest algorithm 5 (信息-摘要算法)缩写,广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过MD5后都能生成唯一的MD5值。实现如下图所示:

参考链接:java常用的加密解密方法_~~wind~fly~~-CSDN博客_java 加密解密
电商项目相关的知识:
并发出现的两个地方:
-
应用服务器高并发
- 负载均衡
- html静态化
- 图片服务器分离 ·
-
数据库高并发
- 读写分离
- 分库、分表 
-
高可用(HA)
- failover 
-
相关文章、网站:
-
高流量访问类型
(1)qq业务模型:只访问自己的数据
(2)秒杀业务模型:秒杀能够只接受前N个请求,后续请求直接返回
(3)奥运会售票业务模型:注册+抽奖,非先来先抢,可以事后线下处理 (4)电子商务业务模型:c2c只需关注自己的库存
(5)b2c库存模型,例如12306业务
阅读原文
线程安全问题
消息中间件
消息中间件是一个消息代理 - 一个消息系统的媒介。它可以为你的应用提供一个通用的消息发送和接收平台,并且保证消息再传输过程中的安全。
常用的MQ:Kafka、RabbitMQ、RocketMQ
RabbitMQ:
-
java client Java Client API Guide — RabbitMQ
kafka:
Redis:
codereview
首先自己使用FindBugs进行代码审查
提交svn后每周组内开会,大家进行代码审查
findbugs使用
findbugs 下载地址:FindBugs Downloads
优化:
sql语句优化:
-
创建必要的索引
在经常检索的字段上创建索引,创建索引会给检索带来巨大的性能提升,因此在发现检索速度过慢的时候应该首先想到就是创建索引。 -
使用预编译查询
程序通常根据用户输入动态执行SQL语句,这个时候应该尽量使用参数化SQL,这样不仅可以避免SQL注入漏洞攻击,最重要的事数据库会对这些参数化SQL执行预编译。这样,第一次执行的时候DBMS会为这个SQL语句进行查询优化并且执行预编译,以后再执行这个SQL的时候就直接使用预编译的结果,这样可以大大的提高执行的速度。 -
调整Where子句中的连接顺序
DBMS一般采用自下而上的顺序解析Where子句,根据这个原理,表连接最好写在其他的Where条件之前,这样就可以过滤掉最大的数据记录。
如下面的SQL性能较差:
select * from T_Person
Where FSalary > 50000
AND FPosition = 'Manager'
AND 25 < (select count(*)from T_Manager where ID = T_Person.FmanagerID)
我们将子句移到前面,这样的SQL性能比较好:
select * from T_Person
Where 25 < (select count(*)from T_Manager where ID = T_Person.FmanagerID)
AND FSalary > 50000
AND FPosition = 'Manager' -
Select 语句中避免使用*
“Select *” 比较简单,但是除非真的需要检索所有的列,否则这样将检索出不需要的列,增加网络负载和服务器的资源消耗。即使确实需要检索所有的列,也不要使用select ,因为这个是一个非常低效的方法,DBMS在解析的过程中,会将 依次转换成所有的列名,这意味着将耗费更多的时间。 -
尽量将多条SQL语句压缩到一句SQL中
每次执行SQL的时候都要建立网络连接,进行权限校验,进行SQL语句的查询优化,发送执行结果,这个过程是很耗时的,因此应该尽量避免过多的执行SQL语句,能够压缩到一句SQL执行的语句就不要用多条来执行。 -
使用表的别名
当在SQL语句中有连接多个表的时候,请使用表的别名并把别名的前缀置于每个列名上,这样就可以减少解析的时间并减少那些有列名歧义引起的语法错误。 -
用EXISTS 替代IN
在查询中,为了满足一个条件,往往需要对另一个表进行连接,在这种情况下,使用EXISTS而不是使用IN,通常将提高查询效率,因为IN子句将执行一个子查询内部的排序和合并。下面的语句2就比语句1效率更高。
语句1:
select * from T_Employee
where FNumber > 0 and FDEPTNO in (select FNumber from T_Department where FmanagerName = 'Tom')语句2:
select * from T_Employee where FNumber > 0
and EXIESTS (select 1 from T_Department were T_Department.ID = T_Empoyee.FDEPTNO and Fmanagement = 'Tom') -
用表连接替换EXISTS
通常来说,表连接方式比EXISTS更有效率,下面的语句比上面的语句2 效率更高
select T_Employee.* from T_Employee ,T_Department d
where T_Employee.FNumber > 0 and T_Department.ID = T_Empoyee.FDEPTNO and d.Fmanagement = 'Tom' -
避免在索引列上使用计算
在Where子句中,如果索引列是计算或者函数的一部分,DBMS优化器将不会使用索引而使用全表扫描。 -
用UNION ALL替换UNION
当SQL语句需要UNION两个查询结果集合的时候,即使检索结果中不会有重复的记录,使用UNION这两个结果集同样会尝试合并结果,然后输出最终结果前进行排序。因此,如果检索结果中不会有重复记录的话,应该用UNION ALL替换UNION,这样效率更高。- 避免隐式类型转换造成全表扫描 Select FID,FAGE,FNAME from T_Person where FAGE =10 (注意“FAGE为String类型的) 在这个SQL语句中,将字符串类型字段FLevel与数值10 进行比较,由于大部分数据库的隐式转换类型中数值类型的优先级高于字符串类型,因此DBMS会对FAGE字段进行隐式类型转换,相当于执行: Select FID,FAGE,FNAME from T_Person where TO_INT(FAGE) =10 所以应该这样写: Select FID,FAGE,FNAME from T_Person where FAGE = ’10‘
-
防止检索范围过宽
如果DBMS优化器认为检索范围过宽,那么它将放弃索引查找而使用全表扫描,下面可能造成检索范围过宽的情况:
(1)使用IS NOT NULL或者不等于判断,可能造成优化器假设匹配的记录数太多。
(2)使用LIEK的时候,"a%"将会使用索引,而"a%c" 和 "%c" 则会使用全表扫描,因此"a%c" 和 "%c" 不能被有效的评估匹配的数量。
项目管理
禅道 使用地址:在线项目管理 云项目管理 git托管 源码托管 - 云禅道
JIRA Jira | Issue & Project Tracking Software | Atlassian
以上是关于近期大厂面试题总结的主要内容,如果未能解决你的问题,请参考以下文章
提问率高达 98%!近期 BATJ 大厂 Java 岗高频面试题~
利用碎片化的时间冲击大厂,从阿里离职归来的表哥手上拿到的 2021 最新大厂面试真题。