一、个人介绍
1.1 线程池 参数
1.2 拒绝策略handler种类
1.第一种AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
2.第二种DisCardPolicy:不执行新任务,也不抛出异常
3.第三种DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
4.第四种CallerRunsPolicy:直接调用execute来执行当前任务
1.3 动态代理实现方式?jdk代理和cglib代理的区别?
动态代理的常用实现方式是反射。反射机制是指程序在运行期间可以访问、检测和修改其本身状态或行为的一种能力,使用反射我们可以调用任意一个类对象,以及类对象中包含的属性及方法。
但动态代理不止有反射一种实现方式,例如,动态代理可以通过 CGLib 来实现,而 CGLib 是基于 ASM(一个 Java 字节码操作框架)而非反射实现的。简单来说,动态代理是一种行为方式,而反射或 ASM 只是它的一种实现手段而已
1.JDK Proxy 是 Java 语言自带的功能,无需通过加载第三方类实现;
2.Java 对 JDK Proxy 提供了稳定的支持,并且会持续的升级和更新 JDK Proxy,例如 Java 8 版本中的 JDK Proxy 性能相比于之前版本提升了很多;
4.JDK Proxy 是通过拦截器加反射的方式实现的;
5.JDK Proxy 只能代理继承接口的类;
6.JDK Proxy 实现和调用起来比较简单;
7.CGLib 是第三方提供的工具,基于 ASM 实现的,性能比较高;
8.CGLib 无需通过接口来实现,它是通过实现子类的方式来完成调用的
1.4 可重入锁volatile和synchronized的区别
1.volatile修饰的变量,jvm每次都从主存(主内存)中读取,而不会从寄存器(工作内存)中读取。而synchronized则是锁住当前变量,同一时刻只有一个线程能够访问当前变量
2.volatile仅能用在变量级别,而synchronized可用在变量和方法中
3.volatie仅能实现变量的修改可见性,无法保证变量操作的原子性。而synchronized可以实现变量的修改可见性与原子性
【1】可见性
说的是一个线程 如果更改了某个变量的值,其他线程能够立刻知道这个变量更改后的值
【2】原子性
一个操作要么全做,要么全不做,就像不可分割的原子一样。银行转账这个操作必须具有原子性,A转账给B1000元,A账户减去1000元,B账户加上1000元,两个操作不可分割,不可单独出现,否则会出现意料之外的结果。
1.5 内存屏障(Memory Barrier),防止指令重排
1.Memory barrier 能够让 CPU 或编译器在内存访问上有序。一个 Memory barrier 之前的内存访问操作必定先于其之后的完成。
2.Memory barrier是一种CPU指令,用于控制特定条件下的重排序和内存可见性问题。Java编译器也会根据内存屏障的规则禁止重排序。
3.有的处理器的重排序规则较严,无需内存屏障也能很好的工作,Java编译器会在这种情况下不放置内存屏障。
LoadLoad屏障:StoreStore屏障:LoadStore屏障:StoreLoad屏障:
1.6 GC算法?CMS、G1区别
引用计数 标记清除 标记压缩 标记拷贝
CMS过程:
1.初始标记(stw)
2.并行标记(产生漏标)- 三色标记 + incremental Update
3.重新标记(stw)
4.并行清除 (产生浮动垃圾 和 碎片)
G1: YGC+MixGC + FullGC(Serial Old)
MixGC:即回收年轻代又回收老年代
MixGC过程:
1.初始标记(stw)
2.并行标记(产生漏标) - 三色标记 + SATB
3.重新标记(stw)
4.并行筛选(移动并压缩)
优化G1:
思路: 减少FGC
1.扩张内存
2.提高CPU
3.降低MixGC阀值,默认是45%
三色标记: 分为黑、白、灰三个颜色
白色: 没有标记
灰色:自身已经标记,成员还没有标记
黑色:自身和成员都已经没有引用
基于漏标有两种解决方案:Increment Update(CMS) 和SATB(Snapshot at the begining)
CMS采用的是 Increament Update
G1: SATB
1.7 OOM和StackOverFlowError的使用场景
1.java.lang.OutOfMemoryError: Java heap space:所以产生这个异样的原因通常有两种:
1.程序中出现了死循环
2.程序占用内存太多,超过了JVM堆设置的最大值。
内存溢出,不是内存泄漏。内存泄漏是指:垃圾回收器无法回收该对象。
2.StackOverFlowError:如果线程请求分配的栈容量超过本地方法栈允许的最大容量时,Java虚拟机将会抛出一个StackOverflowError异常;
1.8 B+树和B树的区别
B树:每个节点都存储key和data,所有节点组成这棵树,并且叶子节点指针为null。
B+树:只有叶子节点存储data,叶子节点包含了这棵树的所有键值,叶子节点不存储指针。【聚簇索引,mysql的Innodb引擎采用的数据结构】
1.9 如何判断链表有环
遍历:出现两个相同节点则证明出现环,利用HashSet存放已遍历的节点,如果发现已经有节点存在于HashSet中,则证明有环出现。
优点:简单
缺点:时间复杂度高O(n),空间复杂度O(n)
1.10 Mybatis的mapper如何映射到sql中
1.MapperRegistry:程序启动之初MyBatis就创建了这个类的一个实例,它有一个HashMap类型的属性用于存储每个Mapper接口(key)和相应的MapperProxyFactory(value);另外有两个重要的方法getMapper()和addMapper(),分别用于获取和注册Mapper接口到这个HashMap中。
2. MapperProxyFactory:正如它的名字mapper代理工厂“,这个类是一个生产mapper代理对象的工厂,而 mapper代理对象负责代替mapper接口完成POJO到数据库的映射。在MapperProxyFactory中的两个重要方法如下,用于创建mapper代理类的一个实例。
3. MapperProxy:通过 调用特定的mapper代理对象的invoke()方法,实现到数据库的映射,实际上invoke()中又调用了MapperMethod中的execute方法,execute方法主要是用到sqlSession的insert、update、select、delete等
1.11 多路IO复用 select pol epoll
多路复用:可以使一个进程监视多个IO,【如java的NIO模型】
select pol epoll 是一次升级的
select是实现多路复用的一个接口,当系统调用select时,程序会等待直到被监视的文件描述符被改变后返回
1.每次select的时候,都需要重新设置fd_set集合
2.每次select时,都需要将fd_set从用户态拷贝到内核态,因为需要系统去监视文件描述符集
3.当随着所监视的文件描述符集增多的时候,效率会降低,因为需要遍历使得开销增大
4.select中的fd_set所监视的文件描述符是有限的的,为1024
poll select中的fd_set用位图来实现,并且作为输入/输出性参数中的不便,poll中就改变了它的fd。poll的函数原型中,其中fds是一个结构体用来监视文件描述符发生的事件,其中fd是文件描述符,events是想要的事件(读、写、异常),revents是用来返回什么事件就绪。将其分开来构成一个结构体,使用起来更直观方便。
poll的缺点:
1.调用poll的时候,也需要将fd从用户态拷贝到内核态
2.和select一样,每次都需要遍历查找就绪的fd
3.虽然没有select的数量限制,但数量过大后性能也会降低
epoll前两种的多路复用方式都没有很好的解决出现的问题,就有了升级版的epoll,其中,epoll_create是用来创建一个epoll句柄,epoll_ctl是对监听文件描述符的操作,epoll_wait则是等待就绪的事件
1.文件描述符无上限,因为内核中用红黑树来管理
2.当文件描述符就绪后,内核会用回调机制将其放到就绪队列中,这样epoll_wait获取时,时间复杂度为O(1)。
3.内核直接将就绪队列通过mmap映射到了用户态,避免拷内的额外开销
1.12 URL输入到地址兰后的变化
1.浏览器查找域名的 IP 地,【DNS具体的查找过程】
2.浏览器向 web 服务器发送一个 HTTP 请求【1.通过访问的域名找出其IP地址2.TCP/TP三次握手3.进入tomcat后如何处理的4.TCP/IP四次挥手】
3.服务器的永久重定向响应
4. 浏览器跟踪重定向地址
5. 服务器处理请求
6. 服务器返回一个 HTTP 响应
7. 浏览器显示 HTML
1.13 TCP/IP三次握手,四次挥手
三次握手 首先client给server发送了一个连接请求,server收到了这个请求并且发送了一个确认应答的请求,站在server的角度,它认为连接已经建立成功了,开始发送数据。但是此时client并没有得到响应,它会认为连接还没有建立成功,将忽略server发送的数据,这样server在发出的数据超时后,会重复的发送数据,就形成了死锁的情况。所以两次握手显然不行。
四次挥手
第一次挥手 当客户端的数据都传输完成后,客户端向服务端发出连接释放报文,需要注意的是客户端发出FIN报文段后只是不能发数据了,但是还可以正常收数据。
第二次挥手 服务端收到客户端发的FIN报文后给客户端回复确认报文,此时服务端处于关闭等待状态,而不是立马给客户端发FIN报文,这个状态还要持续一段时间,因为服务端可能还有数据没发完。
第三次挥手 服务端将最后数据(比如50个字节)发送完毕后就向客户端发出连接释放报文
第四次挥手客户端收到服务端发的FIN报文后,向服务端发出确认报文,服务端一旦收到客户端发出的确认报文就会立马释放TCP连接。