JAVA最全面试题答案整理

支付宝或微信支付

如果因为网络原因或其他原因没有回调, 怎么保证支付状态一致?

token验证

下面我们从一个实例来看如何运用JWT机制实现认证:

登录

  • 第一次认证:第一次登录,用户从浏览器输入用户名/密码,提交后到服务器的登录处理的Action层(Login Action);
  • Login Action调用认证服务进行用户名密码认证,如果认证通过,Login Action层调用用户信息服务获取用户信息(包括完整的用户信息及对应权限信息);
  • 返回用户信息后,Login Action从配置文件中获取Token签名生成的秘钥信息,进行Token的生成;
  • 生成Token的过程中可以调用第三方的JWT Lib生成签名后的JWT数据;
  • 完成JWT数据签名后,将其设置到COOKIE对象中,并重定向到首页,完成登录过程;

请求认证

  • 基于Token的认证机制会在每一次请求中都带上完成签名的Token信息,这个Token信息可能在COOKIE中,也可能在HTTP的Authorization头中;
  • 客户端(APP客户端或浏览器)通过GET或POST请求访问资源(页面或调用API);
  • 认证服务作为一个Middleware HOOK 对请求进行拦截,首先在cookie中查找Token信息,如果没有找到,则在HTTP Authorization Head中查找;
  • 如果找到Token信息,则根据配置文件中的签名加密秘钥,调用JWT Lib对Token信息进行解密和解码;
  • 完成解码并验证签名通过后,对Token中的exp、nbf、aud等信息进行验证;
  • 全部通过后,根据获取的用户的角色权限信息,进行对请求的资源的权限逻辑判断;
  • 如果权限逻辑判断通过则通过Response对象返回;否则则返回HTTP 401;

请求的过程(跟框架有关)

Struts2:

  1. 客户端初始化一个指向Servlet容器(例如Tomcat)的请求
  2. 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin)
  3. 接着FilterDispatcher(现已过时)被调用,FilterDispatcher询问ActionMapper来决定这个请是否需要调用某个Action
  4. 如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
  5. ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
  6. ActionProxy创建一个ActionInvocation的实例。
  7. ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
  8. 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper

这里写图片描述

SpringMVC:

  1. 用户发送请求至前端控制器DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(二者组成HandlerExecutionChain),并将其一并返回给DispatcherServlet。
  4. DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
  5. 执行处理器(Controller,也叫后端控制器)。
  6. Controller执行完成返回ModelAndView
  7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  9. ViewReslover解析后返回具体View
  10. DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet对用户进行响应

这里写图片描述

1. JAVA虚拟机

GC,

2. 垃圾回收机制? 新生代和老年代比例? 回收的方式

jvm 中,程序计数器、虚拟机栈、本地方法栈都是随线程而生随线程而灭,栈帧随着方法的进入和退出做入栈和出栈操作,实现了自动的内存清理,因此,我们的内存垃圾回收主要集中于 java 堆方法区中,在程序运行期间,这部分内存的分配和使用都是动态的.

算法:
1. 标记 -清除算法
2. 复制算法
3. 标记-压缩算法
4. 分代收集算法

JVM GC怎么判断对象可以被回收了?

· 对象没有引用
· 作用域发生未捕获异常
· 程序在作用域正常执行完毕
· 程序执行了System.exit()
· 程序发生意外终止(被杀线程等)

默认的新生代(Young generation)、老年代(Old generation)所占空间比例为 1 : 2 。

3. 一个数据库连接慢, 有多少种可能原因?

  1. 网络问题
  2. 当前链接数已用完, 需等待其他线程释放才能链接

4. 进程和线程的关系

线程: 最小处理单元, 共享内存
进程: 可以包含多条线程, 不共享内存

5. 数据库的索引优化

对于mysql数据库来说,索引的使用是很巧妙的。它设置的好可以提高速度,设置的不好不光无法提高速度,还会造成浪费内存空间。在优化方面,我们首先建立索引,要判断是否需要建立。其次使用的时候,要尽可能避免索引与or,where。。。。。。(此处有至少10条)一起使用。

6. String s= new String(“abc”)创建了几个对象, 分别放在哪里

  1. 两个的情况: 一个是”abc”, 放在堆中的字符串池中, 一个是String对象在堆中, s作为String对象的引用放在栈中

8.java同步的方式

  1. sychronize(方法和同步代码块), jvm自动释放锁
  2. reetrantlock, 需要手动释放, 方法必须放在final里
  3. 使用特殊域变量(volatile)实现线程同步: 它的原理是每次要线程要访问volatile修饰的变量时都是从内存中读取,而不是存缓存当中读取,因此每个线程访问到的变量值都是一样的。这样就保证了同步。
  4. 使用重入锁实现线程同步: ReenreantLock

9.排序方式有哪些,讲一下

快排,

10.堆排序的原理

11.设计模式在java中的应用

单例模式: 静态内部类实现线程安全
懒汉式保证线程安全的方式:
1. 静态内部类

public class Singleton {    
    private static class LazyHolder {    
       private static final Singleton INSTANCE = new Singleton();    
    }    
    private Singleton (){}    
    public static final Singleton getInstance() {    
       return LazyHolder.INSTANCE;    
    }    
}    
  1. 双重检查锁定
public class Singleton {  
 2      private static Singleton instance;  
 3      private Singleton (){
 4      }   
 5      public static Singleton getInstance(){    //对获取实例的方法进行同步
 6        if (instance == null){
 7            synchronized(Singleton.class){
 8                if (instance == null)
 9                    instance = new Singleton(); 
10            }
11        }
12        return instance;
13      }
14      
15  }

12.socket

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

13. http

14. mysql数据库引擎

mysql数据库中,常见的引擎有三种,例如,innoDB,myISAM,memory。其中INNODB的特点是可以用于事务,mvcc的行级锁。特点是ACID,使用的索引通常是B+树,B+树作为索引的特点是有序,连接

15. tcp/ip

1,分为三次握手,四次挥手。(详细点,过程,每一次连接的参数,参数表示的意义)。2,在四次挥手中,其实有两次可以合二为一,就形成了三次挥手。3,第四次挥手的意义有两种,一个是避免无效数据,一个是防止发送异常。4,在第四次挥手中用到了定时器,tcp/ip中一共有四种定时器,分别是重传定时器

  1. 第一次握手:192.168.1.116发送位码syn=1,随机产生seq number=3626544836的数据包到192.168.1.123,192.168.1.123由SYN=1知道192.168.1.116要求建立联机;

  2. 第二次握手:192.168.1.123收到请求后要确认联机信息,向192.168.1.116发送ack number=3626544837,syn=1,ack=1,随机产生seq=1739326486的包;

  3. 第三次握手:192.168.1.116收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,192.168.1.116会再发送ack number=1739326487,ack=1,192.168.1.123收到后确认seq=seq+1,ack=1则连接建立成功。

四次挥手:
1. 客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送(报文段4)。
2. 服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。
3. 服务器B关闭与客户端A的连接,发送一个FIN给客户端A(报文段6)。
4. 客户端A发回ACK报文确认,并将确认序号设置为收到序号加1(报文段7)。

16.从下往上说一下OSI七个分层?

OSI七层模型与TCP/IP五层模型
TCP/IP五层模型: 应用层, 传输层, 网络层, 数据链路层, 物理层
OSI定义了网络互连的七层框架(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层),即ISO开放互连系统参考模型。

17.TCP、UDP属于哪个层?有什么区别?

传输层.

TCP与UDP区别总结:
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付
3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)
4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
5、TCP首部开销20字节;UDP的首部开销小,只有8个字节
6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

18.FTP在哪个层?

应用层

19. 说说SQL中连接(join)?

inner join, left join

20. 说说数据库事务?

用一个常用的“A账户向B账号汇钱”的例子来说明如何通过数据库事务保证数据的准确性和完整性。熟悉关系型数据库事务的都知道从帐号A到帐号B需要6个操作:

1、从A账号中把余额读出来(500)。
2、对A账号做减法操作(500-100)。
3、把结果写回A账号中(400)。
4、从B账号中把余额读出来(500)。
5、对B账号做加法操作(500+100)。
6、把结果写回B账号中(600)。

原子性:
保证1-6所有过程要么都执行,要么都不执行。一旦在执行某一步骤的过程中发生问题,就需要执行回滚操作。 假如执行到第五步的时候,B账户突然不可用(比如被注销),那么之前的所有操作都应该回滚到执行事务之前的状态。

一致性
在转账之前,A和B的账户中共有500+500=1000元钱。在转账之后,A和B的账户中共有400+600=1000元。也就是说,数据的状态在执行该事务操作之后从一个状态改变到了另外一个状态。同时一致性还能保证账户余额不会变成负数等。

隔离性
在A向B转账的整个过程中,只要事务还没有提交(commit),查询A账户和B账户的时候,两个账户里面的钱的数量都不会有变化。
如果在A给B转账的同时,有另外一个事务执行了C给B转账的操作,那么当两个事务都结束的时候,B账户里面的钱应该是A转给B的钱加上C转给B的钱再加上自己原有的钱。

持久性
一旦转账成功(事务提交),两个账户的里面的钱就会真的发生变化(会把数据写入数据库做持久化保存)!

21. 了解数据结构吗?单向链表概念及特点?头部和尾部有什么特点?

链表就是带着指针的结构体,含数据域和指向下一个节点的地址。

头部没有前驱节点,尾部指向NULL
增删快于数组,遍历慢于数组

22. 方法区里存放什么?

已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等等

这里写图片描述

23. 怎样判断是否需要收集?

  1. 什么样的对象是垃圾?一般来说,所有指向对象的引用都已失效,不可能再有程序能调用到这个对象,那么这个对象就成了垃圾,应该被回收。
    1.2 然而引用计数有一个致命问题不好解决,就是循环引用的问题。比如说一个循环链表,他们循环引用者,引用计数永远不会为零,但是实际上程序已经不能访问他们了,他们应该被回收。
    1.3 所以Java实际上是使用基于GC Roots的可达性分析,什么是GC Roots?所有类的静态变量,每个线程调用栈上的本地变量。(实际上我们编程时也是要从这些地方开始访问数据),所有这些对象,以及被这些对象所指向的对象,都是活的对象。活的对象所指向的对象也是活的对象。
    1.4 所以只要在GC的时刻,让程序暂停运行,然后从GC Roots开始分析,最后没有被标记为活对象的对象就是垃圾了。

24. 什么可作为GCRoot的对象?

虚拟机栈中引用的对象。
方法区中类静态属性实体引用的对象。
方法区中常量引用的对象。
本地方法栈中JNI引用的对象。

25. 说说红黑树这个数据结构?

BST存在的主要问题是,数在插入的时候会导致树倾斜,不同的插入顺序会导致树的高度不一样,而树的高度直接的影响了树的查找效率。理想的高度是logN,最坏的情况是所有的节点都在一条斜线上,这样的树的高度为N。
基于BST存在的问题,一种新的树——平衡二叉查找树(Balanced BST)产生了。平衡树在插入和删除的时候,会通过旋转操作将高度保持在logN。其中两款具有代表性的平衡树分别为AVL树和红黑树。AVL树由于实现比较复杂,而且插入和删除性能差,在实际环境下的应用不如红黑树。

26. 了解JDK源码吗?说说ArrayList和HashMap?

ArrayList实现List接口,底层是由数组实现,随机查找速度快0(1),插入和删除因为要移动数组元素所以效率慢。

HashMap实现Map接口。底层是数组加链表实现,线程不安全,允许存储Null键值对。装载因子0.75.

27. Hibernate和Mybatis如何比较?

  1. SQL优化方面:
    Hibernate的查询会将表中的所有字段查询出来,这一点会有性能消耗。
    Mybatis的SQL是手动编写的,所以可以按需求指定查询的字段。
  2. 移植性:
    Hibernate与具体数据库的关联只需在XML文件中配置即可,所有的HQL语句与具体使用的数据库无关,移植性很好。
    MyBatis项目中所有的SQL语句都是依赖所用的数据库的,所以不同数据库类型的支持不好。
  3. JDBC:
    Hibernate是在JDBC上进行了一次封装。
    Mybatis是基于原生的JDBC的。Mybatis有运行速度上的优势。
  4. 动态SQL
    Mybatis mapper xml 支持动态SQL
    Hibernate不支持
  5. 开发工作量
    Hibernate和MyBatis都有相应的代码生成工具。可以生成简单基本的DAO层方法。针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程。

28.说说Spring AOP?

好处: 方法增强
面向切面编程:如声明式事务、日志等功能
AOP原理: 动态代理 1.cglib 2.jdk
区别: jdk实现动态代理的前提必须要有接口, 而cglib不需要接口
如果目标对象没有实现接口, 则默认用cglib

29.IOC呢?注入方式都有哪些?

好处: 分层解耦
解释依赖注入。

之前程序员可通过new创建新实例对象,但是Spring可向容器索取使用注解:@Autowired…

30. 算法题:一个无序数组,其中一个数字出现的次数大于其他数字之和,求这个数字

31. 说一说hashmap,高并发出现的问题,如何改进

如果HashMap到达临界容量需要扩容,两个线程同时进行resize操作,同时开辟两块空间,线程挂起时机不当时,rehash会产生环路。
当然,还会发生,一个线程迭代时,另一个线程做插入删除操作,造成迭代的fast-fail。
根本原因是没有锁机制,一个线程的修改会影响另一个线程的操作。

改用concurrentHashMap

32. 提到concurrenthashmap,细说说原理

HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁,在ConcurrentHashMap内部,段数组是final的,并且其成员变量实际上也是final的,但是,仅仅是将数组声明为final的并不保证数组成员也是final的,这需要实现上的保证。这可以确保不会出现死锁,因为获得锁的顺序是固定的。

ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色,HashEntry则用于存储键值对数据。一个ConcurrentHashMap里包含一个Segment数组,Segment的结构和HashMap类似,是一种数组和链表结构, 一个Segment里包含一个HashEntry数组,每个HashEntry是一个链表结构的元素, 每个Segment守护者一个HashEntry数组里的元素,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。

这里写图片描述

33. 锁分段和CAS算法

CAS: concurrent包的一种乐观锁

CAS的语义是“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”,CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做

34. 说说快排,时间复杂度推算一下

35. MySQL有哪些类型? int占多少位?

4个字节 32位

36.为什么索引能提升效率?

DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。

37. 什么情况下索引失效?为什么失效?

a索引 b索引, 只用到了a索引

1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

2.对于多列索引,不是使用的第一部分,则不会使用索引
where a=3 and c=5… 这种情况下b就是断点,a发挥了效果,c没有效果

3.like查询以%开头

4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引

38. like%..%为什么会扫描全表?遵循什么原则?

因为这样是全模糊查找, 无法使用索引, 所以会扫描全表
索引的最左原则, 因为索引没生效

39. 线程池知道吗?(线程池思想、分类、参数)

分类:
newFixedThreadPool: 创建一个指定工作线程数量的线程池。
newCachedThreadPool: 创建一个可缓存的线程池。
newSingleThreadExecutor: 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,如果这个线程异常结束,会有另一个取代它,保证顺序执行
newScheduleThreadPool: 创建一个定长的线程池,而且支持定时的以及周期性的任务执行
参数:
corePoolSize: 核心线程数
maxPoolSize: 最大线程数
keepAliveTime: 非核心线程闲置时的超时时长
allowCoreThreadTimeout: 设置该时长同样会作用于核心线程
queueCapacity: 队列容量

40.Set如何保证不重复?

hashset的底层是hashmap实现的
底层实际将将该元素作为key放入HashMap。
HashSet中的Value是一个固定值PRESENT。 所以修改不修改无所谓。

41. synchronized实现原理、范围、如何用?

原理:
从上面可以看出,同步代码块是使用monitorenter和monitorexit指令实现的,同步方法(在这看不出来需要看JVM底层实现)依靠的是方法修饰符上的ACC_SYNCHRONIZED实现。
同步代码块:monitorenter指令插入到同步代码块的开始位置,monitorexit指令插入到同步代码块的结束位置,JVM需要保证每一个monitorenter都有一个monitorexit与之相对应。任何对象都有一个monitor与之相关联,当且一个monitor被持有之后,他将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor所有权,即尝试获取对象的锁;
同步方法:synchronized方法则会被翻译成普通的方法调用和返回指令如:invokevirtual、areturn指令,在VM字节码层面并没有任何特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized标志位置1,表示该方法是同步方法并使用调用该方法的对象或该方法所属的Class在JVM的内部对象表示Klass做为锁对象。

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

42. hibernate主键生成策略

  1. increment: 不依赖于底层的数据库, 不适用于集群、同一时段大量用户并发访问的系统…由hibernate管理主键,自动以递增的方式生成标识符
  2. UUID: 所以使用于所有数据库。 占用空间
  3. sequence:
  4. identity: 使用较为方便,但由于依赖于数据库,所以不便于在不同的数据库之间移植程序。由底层数据库生成标识符。identity是由数据库自己生成的
  5. native: 灵活性高,便于程序移植,项目中如果用到多个数据库时,可以使用这种方式。

44. 快速排序思想,给一组数,排一遍

采用了分治的策略

44. 什么叫线程安全? 如何保证线程安全

线程安全:
就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

线程不安全:
就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

45. 1000个饼干,一个有毒,老鼠吃完一周内会死,使用最少的老鼠在一周内找到有毒饼干

根据2^10=1024,所以10个老鼠可以确定1000个瓶子具体哪个瓶子有毒。具体实现跟3个老鼠确定8个瓶子原理一样。
000=0
001=1
010=2
011=3
100=4
101=5
110=6
111=7
一位表示一个老鼠,0-7表示8个瓶子。也就是分别将1、3、5、7号瓶子的药混起来给老鼠1吃,2、3、6、7号瓶子的药混起来给老鼠2吃,4、5、6、7号瓶子的药混起来给老鼠3吃,哪个老鼠死了,相应的位标为1。如老鼠1死了、老鼠2没死、老鼠3死了,那么就是101=5号瓶子有毒。同样道理10个老鼠可以确定1000个瓶子

46. 100个萝卜,一个兔子每次抱50根,从相距50米的起点搬到终点,每走一米吃一根,最多剩多少根?

解答: 因为 它最多搬50根胡萝卜,而每走1米就要吃掉一根萝卜。
那么它第一次搬50根胡萝卜到49米处,然后返回50米处将剩下的50根胡萝卜搬到49米处,这中间去->回->去,一共会吃掉3根胡萝卜;由于一次它最多搬50根胡萝卜,所以只有当剩下的胡萝卜数量小于等于50时,它才不用回去,直接搬到家中。那么我们可以假设 搬了x米后,它不用回返:100-3x <=50 (x为正整数) 解得 x=17所以就可以得到 结果了 100 - 3*17 -(50-17)=16(根)小兔子最多能把16根胡萝卜搬到家里。

47. Java中多态是怎么实现的

在Java中有两种形式可以实现多态。继承和接口。

48. Java中的几种锁

公平锁/非公平锁
可重入锁: 可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。
独享锁/共享锁
互斥锁/读写锁
乐观锁/悲观锁: 悲观锁适合写操作非常多的场景,乐观锁适合读操作非常多的场景,不加锁会带来大量的性能提升。
分段锁
偏向锁/轻量级锁/重量级锁
自旋锁

49. 数据库隔离级别 脏读 幻读 ACID mysql的隔离级别

Read uncommitted
Read committed
Repeatable read
Serializable 序列化

原子性:
是指事务包含的所有操作要么全部成功,要么全部失败回滚

一致性:
是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

隔离性:
是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

持久性:
是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

脏读:
是指在一个事务处理过程里读取了另一个未提交的事务中的数据

不可重复读:
是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

幻读:
是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

50. Linux查看网络 内存 日志命令

来配置并查看网络接口的配置情况: ifconfig
查看进程: ps-ef|grep
所有监听端口及对应的进程: netstat -anp
top: 相当于任务管理器
free: 查看内存
tail cat head: 查看日志

51. spring中有哪些模块

Spring框架的七大模块

  1. Spring Core:
    Core封装包是框架的最基础部分,提供IOC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
  2. Spring Context:
    构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建,比如说通过Servlet容器。

  3. Spring DAO:
    DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。

  4. Spring ORM:
    ORM 封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。

  5. Spring AOP:
    Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你可以定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。而且,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。

  6. Spring Web:
    Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。

  7. Spring Web MVC:
    Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。并且,还可以借助Spring框架的其他特性。

52. equals和hashcode的关系

两个obj,如果equals()相等,hashCode()一定相等。
两个obj,如果hashCode()相等,equals()不一定相等(Hash散列值有冲突的情况,虽然概率很低)。

53. 浏览器中输入URL之后的过程 包括负载均衡 缓存等

  1. DNS域名解析
  2. 建立TCP连接
  3. 发起HTTP请求
  4. 接受响应结果
  5. 浏览器解析html
  6. 浏览器布局渲染

但是,对于大型网站存在多个主机站点,往往不会直接返回请求页面,而是重定向。返回的状态码就不是200 OK,而是301,302以3开头的重定向码,浏览器在获取了重定向响应后,在响应报文中Location项找到重定向地址,浏览器重新第一步访问即可。

补充一点的就是,重定向是为了负载均衡或者导入流量,提高SEO排名。利用一个前端服务器接受请求,然后负载到不同的主机上,可以大大提高站点的业务并发处理能力;重定向也可将多个域名的访问,集中到一个站点;由于baidu.com,www.baidu.com会被搜索引擎认为是两个网站,照成每个的链接数都会减少从而降低排名,永久重定向会将两个地址关联起来,搜索引擎会认为是同一个网站,从而提高排名。

54. 加密解密了解么?几种算法,讲一下你了解的

常用的摘要算法有MD5,SHA1。摘要算法是一个不可逆过程,就是无论多大数据,经过算法运算后都是生成固定长度的数据,一般结果使用16进制进行显示。
MD5和SHA1的区别:MD5结果是128位摘要,SHa1是160位摘要。那么MD5的速度更快,而SHA1的强度更高。

常用的对称加密算法有:AES和DES.
非对称加密(RSA)

55. Mysql的数据库引擎,区别特点

两者最大的差别就是是否支持事务

MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。(因为没有支持行级锁),在增删的时候需要锁定整个表格,效率会低一些。相关的是innodb支持行级锁,删除插入的时候只需要锁定改行就行,效率较高
InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。DELETE 从性能上InnoDB更优,但DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用truncate table这个命令。

56. 对高负载, 高并发有了解么

  1. 单台服务器
  2. 一台演变为两台服务器, 一台web一台db
  3. 增加memcached服务
  4. 增加Web服务器并做MySQL主从
  5. 增加MySQL读写分离
  6. 避免单点引入负载均衡环境
  7. 继续扩充服务规模
  8. 引入NoSQL环境: Redis

57. Hashmap为什么大小是2的幂次

h&(length-1)取模得出的index分布均匀并且碰撞几率低
所以说,当数组长度为2的n次幂的时候,不同的key算得得index相同的几率较小,那么数据在数组上分布就比较均匀,也就是说碰撞的几率小,相对的,查询的时候就不用遍历某个位置上的链表,这样查询效率也就较高了。

58. 堆排序的原理

59. 抽象工厂和工厂方法模式的区别

  1. 抽象工程关键在于产品之间的抽象关系,所以至少要两个产品;工厂方法在于生成产品,不关注产品间的关系,所以可以只生成一个产品。
  2. 抽象工厂中客户端把产品的抽象关系理清楚,在最终使用的时候,一般使用客户端(和其接口),产品之间的关系是被封装固定的;而工厂方法是在最终使用的时候,使用产品本身(和其接口)。
  3. 抽象工厂的工厂是类;工厂方法的工厂是方法。

60. 线程池的使用时的注意事项

  1. 死锁
  2. 系统资源不足: 如果线程池中的线程数目非常多,这些线程会消耗包括内存和其他系统资源在内的大量资源,从而严重影响系统性能。
  3. 并发错误: 线程池的工作队列依靠wait()和notify()方法来使工作线程及时取得任务,但这两个方法难以使用。如果代码错误,可能会丢失通知,导致工作线程一直保持空闲的状态,无视工作队列中需要处理的任务。因为最好使用一些比较成熟的线程池。
  4. 线程泄漏: 异常或错误没有被捕获,那么这个工作线程就异常终止,使线程池永久丢失了一个线程
  5. 任务过载: 当工作线程队列中有大量排队等待执行的任务时,这些任务本身可能会消耗太多的系统资源和引起资源缺乏。

61. Spring中autowire和resourse关键字的区别

  1. @Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;

  2. @Autowired默认是按照类型装配注入的,如果想按照名称来转配注入,则需要结合@Qualifier一起使用;

  3. @Resource注解是又J2EE提供,而@Autowired是由Spring提供,故减少系统对spring的依赖建议使用

62. 消息队列了解么

目的是为了异步处理, 能够实现异步解耦
例子: app的消息推送, 将信息放到mq中, 线程去拿; 注册邮件通知

使用场景的话,举个例子:
假设用户在你的软件中注册,服务端收到用户的注册请求后,它会做这些操作:
校验用户名等信息,如果没问题会在数据库中添加一个用户记录
如果是用邮箱注册会给你发送一封注册成功的邮件,手机注册则会发送一条短信
分析用户的个人信息,以便将来向他推荐一些志同道合的人,或向那些人推荐他
发送给用户一个包含操作指南的系统通知
等等……
但是对于用户来说,注册功能实际只需要第一步,只要服务端将他的账户信息存到数据库中他便可以登录上去做他想做的事情了。至于其他的事情,非要在这一次请求中全部完成么?值得用户浪费时间等你处理这些对他来说无关紧要的事情么?所以实际当第一步做完后,服务端就可以把其他的操作放入对应的消息队列中然后马上返回用户结果,由消息队列异步的进行这些操作。

63. 分布式了解么

64. 介绍redis和mysql的区别

我们知道,mysql是持久化存储,存放在磁盘里面,检索的话,会涉及到一定的IO,为了解决这个瓶颈,于是出现了缓存,比如现在用的最多的 memcached(简称mc)。首先,用户访问mc,如果未命中,就去访问mysql,之后像内存和硬盘一样,把数据复制到mc一部分。

  redis和mc都是缓存,并且都是驻留在内存中运行的,这大大提升了高数据量web访问的访问速度。然而mc只是提供了简单的数据结构,比如 string存储;redis却提供了大量的数据结构,比如string、list、set、hashset、sorted set这些,这使得用户方便了好多,毕竟封装了一层实用的功能,同时实现了同样的效果,当然用redis而慢慢舍弃mc。

  内存和硬盘的关系,硬盘放置主体数据用于持久化存储,而内存则是当前运行的那部分数据,CPU访问内存而不是磁盘,这大大提升了运行的速度,当然这是基于程序的局部化访问原理。

  推理到redis+mysql,它是内存+磁盘关系的一个映射,mysql放在磁盘,redis放在内存,这样的话,web应用每次只访问redis,如果没有找到的数据,才去访问Mysql。

65. Redis的应用场景

缓存服务, 处理高并发场景; 减少对数据库的访问

  1. 在主页中显示最新的项目列表。
  2. 排行榜及相关问题。
  3. 计数。

66. Hashmap中jdk1.8之后做了哪些优化

加入红黑树

比方说恶意的程序,如果它知道我们用的是哈希算法,它可能会发送大量的请求,导致产生严重的哈希碰撞。然后不停的访问这些 key就能显著的影响服务器的性能,这样就形成了一次拒绝服务攻击(DoS)。JDK 8中从O(n)到O(logn)的飞跃,可以有效地防止类似的攻击,同时也让HashMap性能的可预测性稍微增强了一些。

67. 支付宝转账,是如何实现,几个小时通知转账成功的(面试官想让回答长连接,答主一直没get到点)

长连接: 长连接的话,那么这么多次HTTP请求(这些请求包括请求网页内容,CSS文件,JS文件,图片等等),其实使用的都是一个TCP连接,很显然是可以节省很多消耗的。

长短轮询: 对于客户端来说,不管是长轮询还是短轮询,客户端的动作都是一样的,就是不停的去请求,不同的是服务端,短轮询情况下服务端每次请求不管有没有变化都会立即返回结果,而长轮询情况下,如果有变化才会立即返回结果,而没有变化的话,则不会再立即给客户端返回结果,直到超时为止。

第一个区别是决定的方式,一个TCP连接是否为长连接,是通过设置HTTP的Connection Header来决定的,而且是需要两边都设置才有效。而一种轮询方式是否为长轮询,是根据服务端的处理方式来决定的,与客户端没有关系。

第二个区别就是实现的方式,连接的长短是通过协议来规定和实现的。而轮询的长短,是服务器通过编程的方式手动挂起请求来实现的。

68. 对Java的面向对象的理解

java是一门纯粹的面向对象的语言。面向对象这种程序设计模式它将现实世界中的一切事物都看作是对象,例如,一个人是一个对象,汽车、飞机、小鸟等等,都是对象;它强调从对象出发,以对象为中心用人类的思维方式来认识和思考问题。每个对象都具有各自的状态特征(也可以称为属性)及行为特征(方法),java就是通过对象之间行为的交互来解决问题的。

   类是面向对象中一个重要的概念。类是具有相同属性和行为特征的对象的抽象,类是对象的概念模型,对象是类的一个实例,通过类来创建对象,同一类的所有对象具有相同的属性和行为特征。类具有三个基本特征:封装、继承、多态。

   封装就是将对象的属性和行为特征包装到一个程序单元(即类)中,把实现细节隐藏起来,通过公用的方法来展现类对外提供的功能,提高了类的内聚性,降低了对象之间的耦合性。

   继承是对原有类的拓展,举例说明:我现在有一个Person类,但是我想要一个学生对象,他拥有Person类的所有属性和方法,此外他还有学号属性,及上课、写作业等一些方法,我可以创建一个Student类,但是我不想重复写Person类中已经有了的属性和方法,那么,此时我就可以用Student类继承Person类,Student类就拥有了Person类里的属性和方法了,我只需要在Student类里添加另外的新的属性和方法就可以了。Person类就成为父类,Student类就称为子类。父类和子类之间是一般和特殊的关系,子类是一种特殊的父类。此外,子类还可以通过重写来改变父类中的方法,重写可以改变方法的返回类型和访问权限,不能改变方法名称。

 多态是建立在继承的基础上的,是指子类类型的对象可以赋值给父类类型的引用变量,但运行时仍表现子类的行为特征。也就是说,同一种类型的对象执行同一个方法时可以表现出不同的行为特征。

69. Java的finalize,finally,final三个关键字的区别和应用场景

final

当这个关键字修饰一个类时,意味着他不能派生出新的子类,也就是说不能被继承,因此一个类不能被同时声明为abstract和final。当final修饰变量或者方法时,可以保证他们在使用中不会被改变。被声明为final的变量必须在初始化时给定初值,以后在使用时只能被引用而不能被修改。同样,当final修饰一个方法时,这个方法不能被重载。

finally

异常处理时提供finally来执行任何清楚操作。如果抛出一个异常,那么相匹配的catch子句就会被执行,然后控制就会转入finally块。

finalize

方法名。finalize方法在垃圾回收器执行内存对象清理时会调用finalize()方法进行前期的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。

70. 千万用户抢购,如何处理高并发,并且有一个链接,指向前一天抢购成功的用户,如何设计这个系统和数据库

71. 怎么解决session一致性缓存的问题

将session放在redis缓存中, 这样请求过来ngix中, 会先去redis中找session请求

72. 讲一下稳定的排序算法和不稳定的排序算法

通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。在简单形式化一下,如果Ai = Aj, Ai原来在位置前,排序后Ai还是要在Aj位置前。

其次,说一下稳定性的好处。排序算法如果是稳定的,那么从一个键上排序,然后再从另一个键上排序,第一个键排序的结果可以为第二个键排序所用。

72. 动态代理的实现方式和区别

73. 死锁是什么呢? 怎么解决死锁

74. 为什么负载均衡? 怎么实现负载均衡

ngix

如果你发现你的Web站点负载量非常大时,应当考虑使用负载均衡技术来将负载平均分摊到多个内部服务器上。
负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力。
将大量的并发请求分担到多个处理节点。由于单个处理节点的故障不影响整个服务,负载均衡集群同时也实现了高可用性。

75. 数据库挂了怎么办?除了热备份还有什么方法

数据库挂的原因? 场景分析: 高并发原因的话重启也没用.

76. 算法:找出两个数组相等的数,不能用其他数据结构

后来发现有一个 O(n)算法。因为两个数组都是排好序的。所以只要一次遍历就行了。首先设两个下标,分别初始化为两个数组的起始地址,依次向前推进 。推进的规则是比较两个数组中的数字,小的那个数组的下标向前推进一步,直到任何一个数组的下标到达数组末尾时,如果这时还没碰到相同的数字,说明数组中没有相同的数字。

77. 算法:给定一个数字,一个数组,找出数组中相加等于这两个数的和,不能用数据结构

首先也是要对数组进行排序(时间复杂度为O(n*log(n))),然后再已排序的数组中,令i=0,j=n-1,判断arr[i]+arr[j]是否等于target,等于则结束,如果小于target,则i=i+1;如果大于target,则j=j-1,这样查找符合条件的两个元素的过程只需要遍历数组一次,因此查找的时间复杂度降低到O(n),总的时间复杂度还是O(n*log(n))。

78. 介绍分布式事务

简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。

解决方案:
1. 基于XA协议的两阶段提交
2. 消息事务+最终一致性
3. TCC编程模式

79. notify方法为什么唤醒的是等待队列中的任意一个?如何实现的

源码实现的…

80. Synchronized和ReentrantLock的区别

Synchronized关键词属于内置特性: 不需要手动释放锁
ReentrantLock是实现类: 需要手动释放锁, 可能导致死锁

如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作。
因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。

81. 可重入锁的含义?Synchronized是可重入锁吗?如果不是,将产生哪些危害?

Synchronized和ReentrantLock都是可重入锁
如果不是, 可能会产生死锁

82. HTTP1.0,2.0区别,常用的状态码的含义(1XX,2XX,3XX)?

  1. 长连接: HTTP 1.0需要使用keep-alive参数来告知服务器端要建立一个长连接,而HTTP1.1默认支持长连接。
  2. 节约带宽: HTTP 1.1支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,否则返回401。客户端如果接受到100,才开始把请求body发送到服务器。
  3. host域: 现在可以web server例如tomat,设置虚拟站点是非常常见的,也即是说,web server上的多个虚拟站点可以共享同一个ip和端口。HTTP1.0是没有host域的,HTTP1.1才支持这个参数。
  4. 多路复用: HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。
  5. 数据压缩: HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。

200 OK
301 永久重定向
302 临时重定向
400 Bad Request
403 Forbidden
404 Not Found
500 Internal Server Error
501 未实现
502 网关出错

83. HTTP协议的理解(短连接、长连接)?如何理解访问淘宝网站时计算机网路发生的操作?

84. 将n个无序数字,拼接成一个最大的数字(字符串表示即可),要求时间复杂度O(N),空间复杂度O(1)举例:123,54,10,9—->95412310

85. MVC模式理解?优缺点?

MVC的优点
1. 低耦合性: 视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码
2. 高重用性和可适用性
3. 可维护性

缺点
不适合小型,中等规模的应用程序

86. 如何理解Struts框架以及Struts2框架?

struts1的缺陷:
(1).只支持JSP作为表现层技术,不能与Velocity,FreeMarker等技术整合
(2).与Servlet API严重耦合,难于测试
一个exute有四个参数ActionMapping、ActionForm、HttpServletRequest和HttpServletResponse,初始化困难.
(3).侵入式设计,严重依赖于Struts1API,如如ActionMapping、ActionForm和ActionForward类.一旦系统需要重构时,这些类完全没有利用价值,导致较低的代码复用.

Struts2是一种基于MVC的Web应用框架
控制器——FilterDispatcher
动作——Action
视图——Result

87. mysql中常见的数据类型,各自的范围,int(11)中的11的含义

88.ArrayList如何快速排序

使用Collections.sort()传入ArrayList,会采用默认的方式进行排序(字典序)
使用Collections.sort()传入ArrayList和自己实现Commparator接口的类的对象,实现自定义排序
使用List.sort()传入自己实现Commparator接口的类的对象,实现自定义排序
Comparator返回值在jdk1.7、jdk1.8里必须是一对相反数,如1和-1,不能是1和0.因为1.7的排序算法采用timsort,对返回值有严格要求

89. 对称加密和非对称加密区别

90. HTTP 301 302区别 501 502区别

91. threadlocal底层实现

hashmap
首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。

最常见的ThreadLocal使用场景为 用来解决 数据库连接、Session管理等。

92. 两个事务同时操作 如何保证数据一致性

93. 手写算法 求两个字符串的最长公共子串

94. 什么会影响进程的内存

95. 数据库事务特性

96. 如何java实现一个链表

97. 一个很长的字符串(不能放入内存)如何找出重复字符

98. SQL注入,如何防范,预编译原理

SQL语句在程序运行前已经进行了预编译,在程序运行时第一次操作数据库之前,SQL语句已经被数据库分析,编译和优化,对应的执行计划也会缓存下来并允许数据库已参数化的形式进行查询,当运行时动态地把参数传给PreprareStatement时,即使参数里有敏感字符如 or ‘1=1’也数据库会作为一个参数一个字段的属性值来处理而不会作为一个SQL指令。

PreparedStatement可以尽可能的提高访问数据库的性能,我们都知道数据库在处理SQL语句时都有一个预编译的过程,而预编译对象就是把一些格式固定的SQL编译后,存放在内存池中即数据库缓冲池,当我们再次执行相同的SQL语句时就不需要预编译的过程了,只需DBMS运行SQL语句。

所以当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,特别是的大型的数据库中,它可以有效的也加快了访问数据库的速度。

99. Spring事务如何实现,底层做了什么

Spring的事务管理机制实现的原理,就是通过这样一个动态代理对所有需要事务管理的Bean进行加载,并根据配置在invoke方法中对当前调用的 方法名进行判定,并在method.invoke方法前后为其加上合适的事务管理代码,这样就实现了Spring式的事务管理。Spring中的AOP实 现更为复杂和灵活,不过基本原理是一致的。

100. MySQL是如何解决幻读问题的

Repeatable Read (RR)
快照读忽略,本文不考虑。
针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

间隙锁主要用来防止幻读,用在repeatable-read隔离级别下,指的是当对数据进行条件,范围检索时,对其范围内也许并存在的值进行加锁!当查询的索引含有唯一属性(唯一索引,主键索引)时,Innodb存储引擎会对next-key lock进行优化,将其降为record lock,即仅锁住索引本身,而不是范围!若是普通辅助索引,则会使用传统的next-key lock进行范围锁定!

101. 乐观锁和悲观锁的区别和应用场景

102. cglib如何实现动态代理

CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

103. 为什么要用InnoDB

支持事务
支持行级锁和表级锁,能支持更多的并发量
mysql5.6版本开始支持 全文索引
查询不加锁,完全不影响查询

104. B+树和AVL树有什么区别

关键字总数相同的情况下B树的高度越小,磁盘I/O所花的时间越少.

AVL树: AVL树是带有平衡条件的二叉查找树,一般是用平衡因子差值判断是否平衡并通过旋转来实现平衡,左右子树树高不超过1.

适合用于插入删除次数比较少,但查找多的情况。

B+树:是应文件系统所需而产生的一种B树的变形树(文件的目录一级一级索引,只有最底层的叶子节点(文件)保存数据.),非叶子节点只保存索引,不保存实际的数据

105. 如何保证多线程下i++结果正确

加锁 同步

106. 为什么说B+tree比B树更适合实际应用中操作系统的文件索引和数据索引.  

  1. B+tree的内部节点并没有指向关键字具体信息的指针,因此其内部节点相对B树更小,如果把所有同一内部节点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多,一次性读入内存的需要查找的关键字也就越多,相对IO读写次数就降低了.
  2. 由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
  3. ps:我在知乎上看到有人是这样说的,我感觉说的也挺有道理的:
    他们认为数据库索引采用B+树的主要原因是:B树在提高了IO性能的同时并没有解决元素遍历的我效率低下的问题,正是为了解决这个问题,B+树应用而生.B+树只需要去遍历叶子节点就可以实现整棵树的遍历.而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作(或者说效率太低).  

总结面试集中问的几个方面:

Java

  • JVM内存分配机制、内存模型
  • GC(minor GC、major GC、触发条件、GC算法等)
  • 类加载机制(类隔离和类共享)
  • Java集合(List、set、HashMap、HashTable、ConcurrentHashMap等)
  • interface和abstract class
  • socket编程及NIO
  • synchronize、final、static理解
  • 异常(检测异常和未检测异常、继承关系等)
  • 反射、动态代理
  • Spring的IOC、AOP

数据库

  • 第一、第二、第三范式之间的理解和比较
  • 数据库的事务、ACID及隔离级别
  • 索引优化(组合索引、最左匹配原则)、优缺点
  • 手动写创建索引的语句
  • 并发访问场景和所有可能出现的结果、锁作用和实现
  • 主主复制、主从复制
  • B-tree的应用
  • int和varchar
  • io优化
  • 分表分库设计

操作系统/Linux/集群

  • shell脚本、查找文件命令
  • top命令、netstat命令、ifconfig和ipconfig
  • 乐观锁和悲观锁
  • session集群共享
  • Hadoop集群扩容问题
  • 集群负载均衡
  • 虚拟路由
  • Hadoop集群单点故障

计算机网络

  • 传输层协议TCP和UDP
  • http和https(对称加密、非对称加密)
  • ftp和sftp
  • 从访问一个网址到页面出现,描述中间发生的所有事情。

数据结构&算法&设计模式

  • Hash及冲突解决
  • 二叉搜索树
  • 手写快速排序算法、单链表反转、字符串部分逆序(如moc.anis.www转为www.sina.com)
  • 手写二叉树层序遍历、二分查找、递归算法实现
  • 超大文件寻找top K算法设计(单机1M内存、Hadoop集群、外部排序+uniq命令)
  • 算法设计:给定函数a可以等概率产生1-5这5个数,仅调用a实现等概率产生1-7这7个数
  • 用栈实现队列
  • 订单超大并发访问-队列批量处理
  • 观察者模式、工厂模式、适配器模式

项目

每个项目从整体架构设计、扩展性、后续优化到任何实现细节都有可能会问。对做过的事情需要多总结和优化思考。项目这块是需要花大量心思准备的。

猜你喜欢

转载自blog.csdn.net/github_38383183/article/details/78847237