2022.9.12,台州银行
电话一面:
1、java的gc回收机制怎么判断对象可以回收
对象的实例都已经被回收
类的classLoader已经被回收
该类对呀的java.lang.Class对象没有在任何地方被引用,无法通过反射访问该类的方法
可达分析法:从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GCRoots 没有任何引用链相连时,则证明此对象是不可用的,那么虚拟机就判断是可回收对象。
GC Roots的对象有:
虚拟机栈(栈帧中的本地变量表)中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中JNI(Java Native Interface)(即一般说的Native方法)引用的对象
可达性算法中的不可达对象并不是立即死亡的,对象拥有一次自我拯救的机会。对象被系统宣告死亡至少要经历两次标记过程:第一次是经过可达性分析发现没有与GC Roots相连接的引用链,第二次是在由虚拟机自动建立的Finalizer队列中判断是否需要执行finalize()方法。
当对象变成(GC Roots)不可达时,GC会判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。否则,若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。执行finalize方法完毕后,GC会再次判断该对象是否可达,若不可达,则进行回收,否则,对象“复活”。
2、redis的主备机制
Redis的主从复制:
同一个Master可以同步多个Slaves。
Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力。
Master Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。
Slave Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据。
在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。即连上之后,先进行一次全量同步。
此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。后面进行增量同步。
如果Master和Slave之间的链接出现断连现象,Slave可以自动重连Master,但是在连接成功之后,一次完全同步将被自动执行。
3、线程同步和锁的使用
synchronize
volatile关键字
保证了不同线程对这个变量进行操作时的可见性。
即一个线程修改了某个变量的值, 这新值对其他线程来说是立即可见的。
不保证原子性
即不能保证数据在多个线程下同时写时的线程安全
volatile最适用的场景: 一个线程写, 多个线程读
一个线程在修改某个变量的值,其他线程来读取该变量的值都是实时可见的
自旋锁与互斥锁的区别:线程在申请自旋锁的时候,线程不会被挂起,而是处于忙等的状态。
不可重入锁:只判断这个锁有没有被锁上,只要被锁上申请锁的线程都会被要求等待。实现简单
可重入锁:不仅判断锁有没有被锁上,还会判断锁是谁锁上的,当就是自己锁上的时候,那么他依旧可以再次访问临界资源,并把加锁次数加一。
自旋锁spinlock
4、java设计模式
2022.9.23 杭州一真医疗器械
1、java的collection集合的概念
hashmap实现原理
当链表长度大于阈值(默认为 8),转化为红黑树,当红黑树节点小于6,转化为链表。
2、线程创建的方法
Runnable Thread Callable
3、mysql的调优方式
选择最合适的字段属性
mysql在创建数据库的时候首先考虑数据库中的表越小越好,这样才能提高查询的速度。如果数据量过大,比如是以数万或者数十万为单位的,就需要考虑在建表时的字段长度。比如说在存储电话号的时候,如果将其写成CHAR(255),这显然会给数据库带来很多不必要的空间浪费,明明CHAR(11)就可以解决的问题。
使用连接查询(join)代替子查询
子查询的优点是可以使用简单的SELECT语句就可以完成逻辑较为复杂的查询动作,而且还能避免死锁的情况产生。但是有时也可以考虑使用连接查询来完成,毕竟连接查询不需要像子查询一样在内存中创建临时表,再从临时表中过滤数据,从而加快查询速度。
使用union联合查询
union本来就有联合的含义,它可以将多个SELECT语句的查询结果联合到一个查询中,从而替代了手动创建临时表的过程。而且union还有一个好处就是使用完了以后自动就删除了,一点也不占用内存空间。
通过事务来管理
事务是数据库调优时的一个老生常谈的概念,由于其4大特性,事务是不可避免的调优方式之一,它可以保证数据的完整性、一致性。可以用一句话来总结“去不了终点,那就回到原点。”
锁定表
尽管事务能够保证数据库的完整性和一致性,但是它本身其实也存在一些弊端。因为它本身具有一定的独占性,当事务没有执行完毕以前,用户发出的其他操作就只能等待,一直等到所有的事务都结束了才能继续执行。如果用户访问量特别大的时候,这会造成系统的严重延迟问题。
所以可以通过锁定表的方法,保证在没有执行到UNLOCKTABLES指令之前所有被LOCKTABLE修饰地表的查询语句不会被插入、删除和修改。
正确使用索引
索引是提高数据库性能的最常见的方法,能够正确地使用索引,能够大大地提高查询效率。
但是也不能够为所有的列都创建索引,因为它本身会占用内存,维护起来也很麻烦,它就是一把双刃剑,所以索引在使用的时候需要根据实际情况正确使用才行。
优化查询语句
在比较的时候尽量在相同的字段之间进行比较。例如不能将一个带有索引的INT字段和BIGINT字段进行比较;
已将创建了索引的字段上不要使用函数,那样会导致索引失效;
查询时不鼓励使用like语句查询,因为那会消耗掉一部分系统的性能。
mysql和nosql的优缺点
spring的理解
是一个轻量级的IOC和AOP的框架
IOC,依赖注入...
AOP,动态代理...
2022.9.27
新奇点
java回收机制
通过可达性分析计算
如果没有被GC Roots引用的对象会被回收
虚拟根对象有哪些:
虚拟机中栈引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中引用对象
回收算法
1、标记-清除算法
标记出所有需要回收的对象,统一回收
标志清除和会产生大量不连续内存碎片
2、标记-整理算法
在标记清除算法基础上将无需回收的内存移动到另外一边
分代
年轻代:edenty s0 s1,s0和s1之间来回移动,达到阈值之后,移动到老年代中 年轻代中回收叫做Minor GC
老年代:这里回收叫做Major GC
方法区
常见回收器
serial GC
paralll GC
CMS GC
G1 GC
线程池的理解
线程创建使用:继承Thread、实现Runnable,实现Calable
拼频繁创建和销毁线程需要消耗大量时间和资源,所以产生了线程池
线程池解决的问题:
1、线程池是一次性创建指定数的线程,放到线程池中便于管理
2、减少任务的调用开销,执行大量异步任务时对性能改善
3、每次使用完之后将使用完的线程放回线程池,减少销毁的时间和资源
线程池的创建使用Executors工厂
newCachedThreadPool() 无界线程池,自动线程回收
newFixedThreadPool 固定大小的线程池
newSingleThreadExecutor 单个后台线程
2022.10.9 招银网络一面
1、mysql优化措施,联合索引的方式(比如A、B、C三列联合索引,只是查询BC,能否得出结果)
调优手段:一、审视字段长度;二、连接查询代替子查询;三、union联合查询;四、使用索引
联合索引遵循最左前缀原则,所以查询BC索引不生效。
2、主线程和三个子线程之间的执行顺序,先执行子线程,等子线程执行完毕再执行主线程的实现
一、主线程sleep方式,主观,不推荐;二、使用Thread.join
三、使用CountDownLatch,设置latch初始值,然后子线程执行完latch自减,直到为0 ,主线程才执行。
四、同步屏障CyclicBarrier,await到达屏障。
3、线程池的参数说明,线程池的拒绝
六个参数:corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、handler
拒绝策略四个:AbortPolicy(抛异常)、DiscardPolicy(静默丢弃)、DiscardOldestPolicy(喜新厌旧)、CallerRunsPolicy(调用者直接执行)
4、mybatis一级和二级缓存的概念
一级缓存sqlsession、适用经常查询不改值的场景,增删改时会被清空。
二级缓存同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
5、spring事务的传播机制,实现方式
实现方式:编程式事务(代码中体现),声明式事务->传播机制:
6、数据库和redis的一致性方式
一、更新缓存、更新数据库(数据库更新失败问题)
二、更新数据库、更新缓存(A线程更新数据库和缓存之间插入了线程B的更新操作)
三、先删除缓存,再更新数据库(A更新数据之间穿插了B线程的读取操作)解决方式:延迟双删
四、先更新数据库,再删除缓存(A读取数据库并写入缓存的过程中,插入了B线程写操作)解决方式:延迟双删
7、编程将两个有序数据合并
2010.10.10 字节一面
项目聊天
一、springboot的启动流程
- 首先从main找到run()方法,在执行run()方法之前new一个SpringApplication对象
- 进入run()方法,创建应用监听器SpringApplicationRunListeners开始监听
- 然后加载SpringBoot配置环境(ConfigurableEnvironment),然后把配置环境(Environment)加入监听对象中
- 然后加载应用上下文(ConfigurableApplicationContext),当做run方法的返回对象
- 最后创建Spring容器,refreshContext(context),实现starter自动化配置和bean的实例化等工作
二、springboot中mybatis是怎么连接sql语句这些的
1、自动注入mybatis,sqlsessionFactory
2、获取datasource并初始化并放入sqlsessionFactory
3、mapper文件中使用@Mapper注解
三、redis的持久化
RDB和AOF
RDB文件形式记录,恢复快但是存在数据丢失(5分钟一次)
AOF日志形式记录,回复慢但是不存在数据丢失(1s一次)
四、缓存穿透的原理,解决方式
缓存查询不到,直接查询数据库,大规模查询可能导致数据库打挂风险
解决方式:1、接口请求参数的校验;2、当数据库返回空值时,将空值缓存到redis,并设置合理的过期时间;3、布隆过滤器;存储所有可能的key;
缓存击穿
热点key过期后,大量查询导致数据库被打挂
1、增加互斥锁;一个线程获取锁查询完毕之后,写入redis,其他线程从缓存中查询。
2、设置缓存不过期或者后台有线程一直给热点数据续期
缓存雪崩
大量热点数据同一时间过期,大量线程查询直接导致数据库被打挂
击穿解决方案基础之上,将热点key过期时间离散化。
五、bean的注入方式
1、组件注解
2、@Component + @Bean
3、@Import(PlaceHolderClass)快速导入一个组件
4、使用Spring提供的FactoryBean注入
字节二面:
秒杀系统怎么设计
applovin一面
项目介绍
编程题:最长回文子串(暴力法和动态规划)
线程池的原理以及线程执行有几种场景
Threadlocal的原理
synchronized在jdk1.8做了什么优化
hashmap扩容为什么是2倍