赞
踩
注:此博客主要时为了自己面试准备的,文中许多为copy,但基本都附上原博客链接,如果侵权,请告知
java中同包,是指完全相同,不是上级包下级的关系修饰中的同包也是这个意思,即A.B不等于A.B.C
default 关键字
hashmap为什么8个节点变成红黑树 又为什么到了6个节点才恢复为链表?
空间和时间的权衡:因为treenode所占空间大于链表,所以在链表节点较少时,红黑树的查找效率与链表差异不大,只有节点数差别大时再转化为红黑树,至于为什么选取8节点变为红黑树,这是java设计者通过大量hash转化实例后得到一个值,因为每个节点的分布频率会遵循泊松分布,链表长度达到8个元素的概率为百万分之6(0.00000006),至于转化红黑树的阈值8和转化为链表的阈值6不一样,我认为是为了避免频繁来回转化。
-红黑树
节点是红色或黑色。
根是黑色。
所有叶子都是黑色(叶子是NIL节点)。
每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点(简称黑高)。
hascode:返回对象的内存地址的hash值,不同对象可能相同(hash冲突)
equal:比较对象是否相等(地址)
Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去。举例说明:比如,对象A和对象B都属于类S,具有属性a和b。那么对对象A进行拷贝操作赋值给对象B就是:B.a=A.a; B.b=A.b;
序列化实现深拷贝:
泛型详细原理
好处:泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
原理:Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
在调用泛型方法的时候,可以指定泛型,也可以不指定泛型。
在不指定泛型的情况下,泛型变量的类型为 该方法中的几种类型的同一个父类的最小级,直到Object。
在指定泛型的时候,该方法中的几种类型必须是该泛型实例类型或者其子类
CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。
ThreadPoolExcutor构造参数:
corePoolSize: 线程池核心线程数
maximumPoolSize:线程池最大数
keepAliveTime: 空闲线程存活时间(对救急线程而言,下面的unit是单位)
unit: 时间单位
workQueue: 线程池所使用的任务阻塞缓冲队列
threadFactory:线程池创建线程使用的工厂
handler: 线程池对拒绝任务的处理策略,拒绝策略
一般线程池运行流程:
加入一个新任务时,会判断池中运行的线程数是否大于核心线程数,否创建一个线程执行任务,若线程数大于核心线程数则会判断当前任务阻塞队列是否满,未满加入任务队列等待调度,否则判断当前运行中线程数是否大于线程池最大数,小于则创建一个救急线程执行任务,大于则执行拒绝策略。当任务完成时,判断线程空闲时间是否大于最大存活时间,小于则从任务队列提取一个任务执行,大于则通过allowCoreThreadTimeOut判断当前线程池是否允许核心线程池存活超时,是则将救急线程回收,否则将所有线程回收
当前线程可能有多个ThreadLocal类的实例,每个实例保存的变量副本都在这个map中。写入map中的键值对,键是调用set()方法的那个ThreadLocal实例,值就是副本变量
java程序执行流程:
java内存结构
分为
名称 | 特征 | 作用 | 配置参数 | 异常 |
---|---|---|---|---|
程序参数 | 占用内存小,线程私有,生命周期和线程相同 | 记录下一个jvm指令的行位置 | 无 | 无 |
虚拟机栈 | 线程私有,生命周期与线程相同,使用连续的内存 | java方法执行的内存模型,存储局部变量表,操作栈、动态链接、方法出口等信息 | -Xss | StackOverflowError(栈溢出,线程fanfare多)、OutOfMemoryError(内存溢出,线程个数多) |
java堆 | 线程共享 ,生命周期与虚拟机相同,可以不使用连休内存 | 保存实例对象(new)包括数组 | -Xms,-Xmm,-Xsx | OutOfMemoryError |
方法区 | 线程共享,生命周期与虚拟机相同,可以不使用连续内存 | 储存已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码 | -XX:PermSize 16M,-XX:MaxPermSize 64M | OutOfMemoryError |
本地方法栈 | 与虚拟机栈所发挥的作用是非常相似的,区别为虚拟机使用到的Native 方法服务 |
java运行时数据区域-----程序计数器
运行时常量
方法区一部分,(静态常量池 存在于class文件中)
Stringtable串池:储存字符串常量
常量池、运行时常量池、stringTable
年轻代回收:
四种算法:
1、根搜索算法
2、复制算法
3、标记清除算法
4、标记压缩算法
七种回收器:
1、serial
2、serial old
3、parnew
4、parallel scavenge
5、parallel old
6、CMS
7、Gabage first (G1)
G1回收过程
G1的垃圾回收流程和CMS很相似,具体过程如下:
1.初始标记
该阶段仅标记GC根节点能够直接关联的对象(需要Stop-The-World,但耗时很短);
2.并发标记
从GC的根节点对heap中的对象进行可达性分析,标记出存活的对象。并发标记耗时比较长,但是可以和用户程序并发执行。
3.最终标记
最终标记是为了修正并发标记期间用户程序运行而导致标记变动的那部分标记记录。JVM将并发标记这段时间用户程序对heap中对象的修改记录保存到Remember Set Logs中,在最终标记阶段,JVM将Remember Set Logs同步到Remember Set中(需要停顿线程,但是可以并发执行)。
4.筛选回收
G1首先对各个Region的回收价值和成本进行排序,根据用户期望的停顿时间来制定回收计划,即根据可停顿时间长短来回决定收多少Region。此时可以采用可用户程序并行方式,但是Stop-The-World可以极大提高回收效率。
1、掘金
2、博客园
3、Java 关于强引用,软引用,弱引用和虚引用的区别与用法
ReferenceQueue
1、操作系统【总】git
2、读者写者问题(读者优先、写者优先、公平竞争)
3、死锁的四个必要条件?如何避免与预防死锁?
4、页面置换算法
物理层——集线器:放大比特能量强度放大,从而扩大网络的传输距离(碰撞)
链路层——交换机:不会发生碰撞,能根据 MAC 地址进行存储转发。具有自学习能力,学习的是交换表的内容,交换表中存储着 MAC 地址到接口的映射
(网络层实现主机之间的通信,而链路层实现具体每段链路之间的通信。因此在通信过程中,IP 数据报的源地址和目的地址始终不变,而 MAC 地址随着链路的改变而改变)
网络层——路由器:
ip首部 20字节
ARP协议: 实现由 IP 地址得到 MAC 地址。
路由选择协议:RIP、ospf、BGp
传输层:
udp首部:8字节;tcp首部:20字节
HTTP:是互联网上应用最为广泛的一种网络协议,是超文本传输协议,信息是明文传输,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,具有安全性的ssl加密传输协议,HTTPS的安全基础是SSL
HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。
首先检查浏览器缓存,没有则向本地缓存查找,没有则查找本地host文件,没有向路由器缓存查找,没有则向本地dns服务器发起域名解析,本地dns服务器缓存没有击中则向根域名服务器发起请求,根域名服务器负责解析客户机请求的根域名部分,它将包含下一级域名信息和DNS服务器地址,返回给客户机的本地DNS服务器,本地dns服务器再通过向下一级域名服务器解析发起请求获取再下一级域名服务器地址,通过这样的迭代方法解析完最终域名对应的ip,本地dns服务器进行缓存同时将ip返回给客户机,客户机解析器拿到结果后,缓存再本地的dns缓存中,返回给浏览器,浏览器也会缓存一段时间,获取ip地址后就可以选择tcp或者udp协议进行通信了,如果是tcp协议,则要进行三次握手,建立连接后就可以发送http请求进行数据传输,之后浏览器再进行页面渲染
DNS域名解析原理与迭代和递归的区别
所谓 递归查询过程 就是 “查询的递交者” 更替, 而 迭代查询过程 则是 “查询的递交者”不变。
比如本机向本地DNS服务查找过程是查找者由本机查找变为本地DNS服务器查找,而本地DNS服务器向根域名服务器查找时,是同过根域名返回下一个查询目标给本地DNS服务器,然后还是由本地DNS服务器继续去查询
TCP粘包和拆包
TCP是个流协议,所谓流,就是没有界限的一连串数据。所以tcp无法理解业务数据的含义,它会根据缓冲区的实际情况进行包的划分,所以对于业务来说,一个完整的包可能会被拆分成多个小包来传输,也可能把多个小包封装为一个大包进行传输,即TCP的拆包和粘包
粘包、拆包问题的解决方案:定义通信协议
定长协议:例如规定3个字节为一个有报文
特殊字符分隔协议:在包尾增加特殊字符如空格进行分隔
长度编码:将消息分为消息头和消息尾,头部用一个int记录消息尾部实际长度占字节数length,读取数据时先获取length信息,后续的尾部读取长度必须和length一样才认为读取了完整的数据报文
HTTP协议浅析(8种请求方法、GET和POST区别、幂等性、HTTP和HTTPS)
GET 和 POST 区别:
说到GET和POST,首先他们都是基于TCP/IP协议,二者数据传输都是建立在TCP连接上的,所以二者本质上是没多大区别,因此二者的区别我觉得更多在于使用规范上
GET 参数通过 URL 传递,并且长度有限制,而 POST 放在 request body 并且长度没有限制。
在符合REST规范中,GET 用于获取资源,而 POST 用于传输实体主体
幂等性,同样的请求被执行一次与连续执行多次的效果是一样的,即对服务器不产生副作用,GET符合幂等性,POST则不符合,所以GET对服务端来说是安全的,POST则不安全
上面说的都是符合使用规范为前提,怎么使用还是取决于我们的实际代码,我们也可以通过get更新更新操作,使其不符合幂等性,但这样的行为是不可取,会让我们的代码可维护性和二次开发性更低
除了上面所说的规范区别,GET和POST二者在传输上还有个不同就是
GET产生一个TCP数据包,POST产生两个
对于GET请求,浏览器会将HTTP header和 data一起发送给服务端,服务端返回200
对于POST请求,浏览器会先将HTTP header发送给服务端,返回100后再将data传输,再返回200(当然了,并不是所有浏览器,Firefox只发一次)
1、SpringIOC和AOP原理 设计模式 简书
IOC:
1、用户发送请求至前端控制器DispatcherServlet。
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView。
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、ViewReslover解析后返回具体View.
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。
1、Mybatis常见面试题总结
2、Mybatis插件原理(一)-- 简单编写Mybatis插件
一、Mybatis插件运行原理
1.mybatis可以编写针对Executor、StatementHandler、ParameterHandler、ResultSetHandler四个接口的插件,mybatis使用JDK的动态代理为需要拦截的接口生成代理对象,然后实现接口的拦截方法,所以当执行需要拦截的接口方法时,会进入拦截方法(AOP面向切面编程的思想)
二、写一个插件,分三步完成
1.编写Intercepror接口的实现类
2.设置插件的签名,告诉mybatis拦截哪个对象的哪个方法
3.最后将插件注册到全局配置文件中
幻读指的是在同一事务下,连续执行两次同样的SQL语句第二次的SQL语句可能返回之前不存在的行;
可重复读指的是同一行在同一个事务下无论怎么读取都是同一个结果(除非自己把它改了);
MVCC的理解:(多版本是指数据快照版本)
答:MVCC即多版本并发控制,它是基于乐观解决并发数据并发一致性问题的,在mysql中的innodb就是采用MVCC实现提交读和可重复读,它使数据读-写可并发执行,极大提高了mysql效率,mysql实现MVCC是通过维护一个readview,里面储存是未提交事务链和该事务链的最大和最小事务版本id,在进行普通的select操作时,会通过比较数据快照行的版本id和readview中的最大最小id关系,
(1)当其id<最小id时,说明该数据快照在所有未提交事务前,可使用
(2)当其id>最大id时,说明该数据快照时在事务开启后修改的,不可使用
(3)当最小id<id<最大id时,需要根据当前的事务隔离级别进行判断
(3.1)可提交读:如果id在redview中,表面该事物未提交所以数据快照 不可使用,否则可使用
(3.2)可重复读:数据快照不可使用,因为该数据快照在未提交事务后,说明未提交事务都可以访问到并修改,会出现不可重复问题
当数据快照不可使用时,会通过回滚指针回滚到undo日志中的上一个数据快照继续执行上面的操作
MVCC解决不了幻读,因为数据访问都是加锁的访问的,因此都是当前读,而不是快照读,mysql innodb通过mvcc+nextkey-lock实现串行读,nextkey-lock是锁定当前数据索引即索引间隙
1、MySQL存储引擎MyISAM和InnoDB索引实现的不同(存储结构)
2、数据库mysql
3、主键索引和非主键索引的区别
主键索引和非主键索引的区别是:非主键索引的叶子节点存放的是主键的值,而主键索引的叶子节点存放的是整行数据,其中非主键索引也被称为二级索引,而主键索引也被称为聚簇索引。
主键查询的方式,则只需要搜索 ID 这棵 B+树。
非主键的查询方式,则先搜索k索引树,得到ID=100,再到ID索引树搜索一次,这个过程也被称为回表。
悲观锁:读取时加锁,更新完释放锁,再此过程中会造成其他线程阻塞,导致吞吐量低,适用于多写场景。
乐观锁:不加锁,只有在更新时验证数据是否被其他线程更新,吞吐量较高,适用于多读场景。
6、MySQL中普通索引和唯一索引的区别详解
7、myqsl执行过程
1、redis概要
2、Redis3.2源码分析-字典dict
第一种情况:因为redis是基于key-val的存储系统,整个db的键空间就是一个大字典,这个字典里放了许多key-val对,不论value是String、List、Hash、Set、Zset中的哪种类型,redis都会根据每个key生成一个字典的索引。
第二种情况:若value的类型是Redis中的Hash,在Hash数据量较大的情况下 redis会将Hash中的每个field也当作key生成一个字典(出于性能考虑,Hash数据量小的时候redis会使用压缩列表ziplist来存Hash的filed),最终 Hash的key是一个字典的索引,key中的所有field又分别是另一个字典的索引。
3、数据结构之Redis-跳表
4、Redis 分布式锁
为了解决分布式架构系统中的高并发问题
redis 实现分布式锁的话是通过命令set key value [nx|xx] [ex|px] seconds实现,其中:
nx-只有键key不存在的时候才会设置key的值,
xx - 只有键key存在的时候才会设置key的值,
ex -设置建key过期时间,秒为单位
px -设置键key过期时间,毫秒为单位
那时候为了加深理解还写过一个模拟秒杀商品的小demo,使用的就是redis实现分布式锁,具体实现思路是:
1、以商品id为锁key
2、设置唯一标识为锁的value(用作释放锁的判断条件,避免其他进程释放自己的锁
3、在获取锁的同时设置锁的过期时间(二者为原子操作避免系统宕机导致死锁)
stringRedisTemplate.opsForValue().setIfAbsent(key,clientId,30, TimeUnit.SECONDS);
4、使用try finally块在方法运行完后释放锁。
5、在获取锁后开启一个分线程,使用定时器每隔一个时间段查看进程自己的锁是否过期,时间段=初始时间/3,如果还未过期,则恢复为初始时间,避免在因为运行超过过期时间导致redis自己释放锁。
后面也有去网上看过分布式锁的相关实现,发现了redisson框架可以很简单实现我原来的这个小demo的功能,去了解了一下redisson底层实现思想发现和我的原先思想挺相似的
分布式锁性能优化:
因为redis为单线程(但其并发量可达几万),所以分布式锁是将并发进程变为串行执行,如果想提高效率,如上面的秒杀商品,可将redis中的product1分段存储,比如product1:100 分为
prouduct1_01:10、product1_02:10、product1_03:10…product1_10:10,
到时候分布式锁就可以锁分段后的商品id,这样效率会是原先秒杀product1的10倍。这也是我看了ConcurrentHashMap的底层分段锁的源码得出的启示。
5、redis的持久化方式RDB和AOF的区别
1、快速排序(java实现)
2、带哨兵java实现插入排序和希尔排序
46个Linux面试常见问题送给你
查看cpu和内存
free命令是用来查看内存使用情况的主要命令。和top命令相比,它的优点是使用简单,并且只占用很少的系统资源。通过-S参数可以使用free命令不间断地监视有多少内存在使用,这样可以把它当作一个方便实时监控器。
孤儿进程与僵尸进程[总结]
1、一文读懂分布式事务一致性
两段式事务提交指的是在执行提交commit操作前,添加预提交prepare操作,其中预提交操作执行了传统意义上提交操作的大部分工作,我们可以简单地认为只要预提交prepare操作成功,后续的提交commit操作一定会成功。
springboot+mybatis+druid+atomikos 处理分布式事务
问题:一个5升水桶、一个3升水桶,吴无限水,不可以使用额外容器,怎么盛4升水
答案:3+3-5+3 即先用3升水桶往5升水桶中装两次,这时3升水桶还剩1升,倒掉5升水桶水,将3中水导入5,再盛满3,再导入5即可
问题:[面试题]1000瓶毒药里面只有1瓶是有毒的,问需要多少只老鼠才能试出那瓶有毒。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。