整篇

阿王 2022-10-12 01:27:33 18623 0 0 0

1111 Java基础问题======================================

B5、【初级】面向对象编程有哪些特点?

  • 封装
    (了解)解释:是指隐藏对象的属性和实现的细节,仅对外提供公共访问方式。
    目的:
    (1)隐藏实现细节,代码安全。
    (2)简化代码,增强了代码的复用性。
    (3)减少耦合,分工明确。
  • 继承
    (了解)解释:子类继承父类的特征和行为。
    目的:实现代码的复用。
  • 多态
    (了解)解释:同一个行为的多个不同表现形式。
    目的:使程序更灵活,扩展性更强。(以不变应万变,usb接口)
    (**经常问**)必要条件:
    (1)继承或实现接口
    (2)父类引用指向子类
    (3)重写

    重写与重载的区别

  • 重写 总结:
    1.发生在父类与子类之间
    2.方法名,参数列表,返回类型必须相同
    3.访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)
    4.重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常
  • 重载 总结:
    1.重载Overload是一个类中多态性的一种表现
    2.重载要求同名方法的参数列表不同(参数类型,参数个数甚至是参数顺序)
    3.重载的时候,返回值类型可以相同也可以不相同。不能根据返回类型进行区分

B6、【初级】== 和 equals 的区别是什么?

(1)==是一个比较运算符,基本数据类型比较的是值,引用数据类型比较的是地址值。(比较地址值即是指是否为同一个对象的引用)
(2)equals()是一个方法,只能比较引用数据类型。重写前比较的是地址值,重写后比一般是比较对象的属性。

B9、【中级】请说一下ArrayList的扩容机制

(1)ArrayList的底层结构是一个数组。默认长度是10。
(2)当数组被存储占满时触发扩容,新数组长度为原长度的1.5倍。
(3)当数组扩容时,会创建一个原数组长度1.5倍的新数组,然后再把数据从原数组中拷贝到新数组中。

B9、【中级】请说一下HashMap的扩容机制

(1)底层数据存储结构是数组+链表+红黑树
(2)数组的默认长度为16
(3)负载因子为0.75,也就是说当使用容量达到总长度的四分之三时,触发扩容,新的数组长度为原数组长度的2倍。
(4)当key发生hash碰撞时,产生链表。当链表的长度大于8并且数组长度大于64时,产生红黑树。
(5)容量小于64,链表长度大于等于8也会触发一次扩容。

B10、【中级】你都用过哪些设计模式?

(1)单例模式
(2)工厂模式
(3)代理模式:动态代理和静态代理。其中动态代理包括JDK代理和CGLIB代理

B11、【中级】单例模式有哪些实现方式?

饿汉式
(1)在程序启动时创建对象
(2)优点:线程安全的
(3)缺点:影响启动速度。如果这个对象从来被使用过,会导致占用多一点内存

懒汉式
(1)在使用对象的时候才创建对象
(2)优点:不会占用更多内存
(3)缺点:不是线程安全的,因此一般会在创建对象时加锁

B12、【中级】hashcode和equals有啥关系?

(1)判断两个对象是否为同一个对象时,优先判断hashcode是否相同。
(2)如果hashcode相同,会再次调用equals来判断是否为同一个对象。
(3)一般重载equals时,需要先重载hashcode,否则在判断对象的值是否相同时,可能不会被调用。
(4)hashcode的作用是加快查找和比较对象。

B13、【初级】JDK1.8有哪些新特?

(1)接口中的默认方法
(2)函数式接口
(3)Lambda表达式
(4)Stream API

B14、【初级】Stream和Collect有啥区别?

(1)集合(Collect)主要侧重的是数据和存储。
(2)流(Stream)主要侧重的是计算。

B15、【初级】创建类有哪几种方法?

(1)通过new关键字创建
(2)通过反射创建
(4)使用克隆【clone()】的方法
(5)通过反序列化方法

B19、【初级】JDK、JRE、JVM他们之间有什么区别?

(1)JVM,全称Java Virtual Machine(Java虚拟机),是一种用于计算设备的规范,它是一个虚构出来的计算机,引入JVM后,Java语言在不同平台上运行时不需要重新编译。JVM是Java跨平台的核心。
(2)JRE,全称Java Runtime Environment,是指Java的运行环境,是可以在其上运行、测试和传输应用程序的Java平台。
(3)JDK,全称Java Development Kit,是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的Java应用程序。JDK是整个Java开发的核心。
(4)三者关系如下:
JDK = JRE + 开发工具集(例如Javac编译工具等)
JRE = JVM + Java SE标准类库

B20、【中级】String、StringBuffer与StringBuilder之间有什么区别?

String StringBuffer StringBuilder
String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间 StringBuffer是可变类,是线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 可变类,速度更快
不可变 可变 可变
线程安全 线程安全 线程不安全
多线程操作字符串 单线程操作字符串

处理内容变换时的速度对比:
StringBuilder 》 StringBuffer 》 String

2222 Java的线程问题======================================

T2、【初级】线程的创建有哪几种方式?

(1)继承Thread类,重写run方法。
(2)实现Runnable接口,重写run方法。
(3)实现Callable接口,重写call方法
(4)通过线程池创建。

T4、【中级】线程池的参数有哪些?

(1)corePoolSize 线程池核心线程大小
(2)maximumPoolSize 线程池最大线程数量
(3)keepAliveTime 空闲线程存活时间
(4)unit 空闲线程存活时间单位
(5)workQueue 工作队列

ArrayBlockingQueue
LinkedBlockingQuene
SynchronousQuene
PriorityBlockingQueue
(6)threadFactory 线程工厂
(7)handler 拒绝策略

  • 第一种拒绝策略是 AbortPolicy,这种拒绝策略在拒绝任务时,会直接抛出异常 RejectedExecutionException (属于RuntimeException),让你感知到任务被拒绝了,于是你便可以根据业务逻辑选择重试或者放弃提交等策略。
  • 第二种拒绝策略是 DiscardPolicy,这种拒绝策略正如它的名字所描述的一样,当新任务被提交后直接被丢弃掉,也不会给你任何的通知,相对而言存在一定的风险,因为我们提交的时候根本不知道这个任务会被丢弃,可能造成数据丢失。
  • 第三种拒绝策略是 DiscardOldestPolicy,如果线程池没被关闭且没有能力执行,则会丢弃任务队列中的头结点,通常是存活时间最长的任务,这种策略与第二种不同之处在于它丢弃的不是最新提交的,而是队列中存活时间最长的,这样就可以腾出空间给新提交的任务,但同理它也存在一定的数据丢失风险。
  • 第四种拒绝策略是 CallerRunsPolicy,相对而言它就比较完善了,当有新任务提交后,如果线程池没被关闭且没有能力执行,则把这个任务交于提交任务的线程执行,也就是谁提交任务,谁就负责执行任务。这样做主要有两点好处。
  • 第一点新提交的任务不会被丢弃,这样也就不会造成业务损失。
  • 第二点好处是,由于谁提交任务谁就要负责执行任务,这样提交任务的线程就得负责执行任务,而执行任务又是比较耗时的,在这段期间,提交任务的线程被占用,也就不会再提交新的任务,减缓了任务提交的速度,相当于是一个负反馈。在此期间,线程池中的线程也可以充分利用这段时间来执行掉一部分任务,腾出一定的空间,相当于是给了线程池一定的缓冲期。

T6、【中级】线程池都有哪些类型?3

(1)缓存型线程池:
(2)固定长度线程池
(3)可定时执行的线程池
(4)单线程化线程池

T7、【中级】线程的状态都有哪些?

T9、【中级】synchronized与Lock有啥区别?

(1)synchronized是java内置关键字,在jvm层面,Lock是个java接口;
(2)synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
(3)synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
(4)用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
(5)synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
(6)lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。

T10、【中级】start()和run()有啥区别?

(1)start()方法来启动线程,真正实现了多线程运行。这时无需等待 run 方法体代码执行完毕,可以直接继续执行下面的代码。
(2)通过调用 Thread 类的 start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。
(3)方法 run()称为线程体,它包含了要执行的这个线程的内容,线程就进入了运行状态,开始运行 run 函数当中的代码。 Run 方法运行结束, 此线程终止。然后 CPU 再调度其它线程。

T11、【初级】wait()和sleep()有啥区别?

(1)对于 sleep()方法,我们首先要知道该方法是属于 Thread 类中的。而 wait()方法,则是属于Object 类中的。
(2)sleep()方法导致了程序暂停执行指定的时间,让出 cpu 该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
(3)在调用 sleep()方法的过程中,线程不会释放对象锁。
(4)而当调用 wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用 notify() 方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
(5)wait():当线程等待状态为真,其他程序申请线程时,该线程会释放线程锁;如果该线程调用notify()方法,本线程 会进入对象锁定池准备,获取对象锁进入运行状态。
(6)sleep():程序暂停执行指定的时间,释放cpu资源,在调用sleep()方法的过程中,线程不会释放对象锁。当指定时间到了,就会自动恢复运行状态。

T12、【初级】notify()和notifyAll()有啥区别?

(1)notify()随机唤醒一条线程;
(2)notifyAll()唤醒全部的线程。

T13、悲观锁和乐观锁有啥区别?

(1)悲观锁认为对于同一个数据的并发操作一定是会发生修改的,采取加锁的形式,悲观地认为,不加锁的并发操作一定会出问题。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中Synchronized和ReentrantLock等独占锁就是悲观锁思想实现的。
(2)乐观锁正好和悲观锁相反,它获取数据的时候,并不担心数据被修改,每次获取数据的时候也不会加锁,只是在更新数据的时候,通过判断现有的数据是否和原数据一致来判断数据是否被其他线程操作,如果没被其他线程修改则进行数据更新,如果被其他线程修改则不进行数据更新。Lock 是乐观锁的典型实现案例。

T15、多线程有哪些特性?

(1)原子性
(2)可见性:保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
(3)有序性:通过synchronized和lock来保证有序性

3333关系型数据库的问题======================================

D5、【初级】Mysql数据库的存储引擎有哪些?

(1)InnoDB存储引擎:提供了良好的事务处理、崩溃修复能力和并发控制。缺点是读写效率较差,占用的数据空间相对较大。
(2)MyISAM存储引擎:优势在于占用空间小,处理速度快。缺点是不支持事务的完整性和并发性。
(3)MEMORY存储引擎:数据读写速度快。缺点是如果重启或者关机,所有数据都会消失。

D6、【初级】数据库设计三大范式?

(1)第一范式(1NF):列不可再分
(2)第二范式(2NF)属性完全依赖于主键
(3)第三范式(3NF)属性不依赖于其它非主属性,属性直接依赖于主键

D7、【初级】你对数据库中的冗余字段是怎么理解的?

(1)缺点:占用存储空间、修改效率底
(2)优势:适当的冗余可以提升查询速度

D8、【初级】数据库的事务有哪些特性?

(1)原子性(Atomicity):最小的执行单元,不可分割,事务要么全部被执行,要么全部不执行
(2)一致性(Consistency):数据库从一种正确状态转换成另外一种正确状态,同步更新
(3)隔离性(Isolation):每个事务都是独立存在,互不影响。
(4)持久性(Durability):事务正确提交之后,其结果将永远保存在数据库之中。

D9、【初级】数据库的事务隔离级别有哪些?

(1)read_commited(读已提交)
(2)read_uncommitted(读未提交)
(3)repeatable_read(可重复读)默认
(4)serlalizable(串行化)

(1)脏读:事务A读到了事务B还没有提交的数据
(2)不可重复度(虚读):在同一个事务中前后多次,读出来的数据内容不一致。
(3)幻读:在一个事务里面的操作中发现了未被操作的数据。(前后多次读取,数据总量不一致,常发生在添加 或者 删除)

D12、【高级】数据库事务的底层是如何实现?

(1)通过undo log和redo log保证了事务的原子性和持久性
(2)通过mvcc和锁来保证事务的隔离性。
(3)保证了事务的原子性,持久性和隔离性就做到了事务的一致性。

D13、【中级】说说你对乐观锁的理解?

(1)不会阻塞,允许多个线程同时访问,但是只能有一个线程操作成功。
(2)一般会使用版本号或CAS实现,适用于读多写少的场景。

D14、【中级】说说你对悲观锁的理解?

(1)会阻塞,保证同一时刻,只有一个线程能够操作数据,其他线程阻塞挂起。
(2)Java中synchronized,lock,数据库中读锁,写锁等都是悲观锁的实现,适用于读少写多的场景。

D15、【中级】什么时候要用乐观锁?什么时候要用悲观锁?

(1)读多写少的时候用乐观锁
(2)写多读少的时候用悲观锁

D16、【中级】数据库锁有哪些?

(1)表锁
- 读锁:所有线程只允许对当前表进行读操作,不允许写操作。
- 写锁:只允许当前线程对表进行读写操作,其他线程既不能读也不能写。

(2)行锁
- 共享锁:多个事务可以共同对同一数据加锁,共同使用一把锁,所有事务都可以进行读操作,但是只有当其他事务操作完成(释放锁)之后才能进行写入或更新。
- 排它锁(独占锁):同一数据只能有一个事务进行加锁,当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。

D17、【中级】SQL优化你们是怎么做的?

(1)问题定位:找出慢查询语句或者CPU飙高的语句
(2)SQL语句分析:通过explain查看SQL的执行计划
(3)解决: 表设计、表索引、SQL语句中的问题

D18、【中级】你们是如何排查慢查询语句的?

(1)方法一:我们使用的是德鲁伊数据库连接池,他有一个web页面,可以查看哪些语句是慢查询语句。
(2)方法二:开启MySQL的慢查询日志,通过日志也可以查看哪些语句是慢查询语句。

D19、【中级】SQL查询中哪些情况会导致索引失效?

(1)查询条件中索引列使用了函数,比如日期转换,字符串处理,计算,统计等等,会导致索引失效。
(2)模糊查询like以%号开头会导致索引失效。
(3)范围查询可能会导致索引失效,in,or,is null,<>等。
(4)如果数据库中存储的数据很少,mysql的执行引擎认为全表扫描会比索引扫描更快,就不会再去查索引了。
(5)复合索引要遵循最左侧匹配原则,查询条件中如果没有最左侧列会导致索引失效。

D21、【中级】数据库索引的结构有哪些?

Mysql支持多种索引结构类型,哈希表,全文索引,B-Tree,B+Tree等。
(1)哈希表:只有memory存储引擎下支持哈希索引,底层哈希表,存储原理和HashMap类似。
(2)全文索引:MyISAM支持全文索引,生成全文索引非常消耗时间和空间,所以一般不会通过数据库做全文索引,通过sorl或es搜索引擎解决。
(3)B-Tree:B-Tree是多叉平衡树,每个节点保存索引值和数据。
(4)B+Tree:B-Tree的优化,数据保存到叶子节点,非叶子节点存储数据的地址。

D22、【初级】数据库的索引有哪些?

(1)主键索引:是一种特殊的唯一索引,在一张表中只能定义一个主键索引。
(2)唯一索引:唯一索引,不允许被索引列数据重复,可以为null,比如:学号,身份证号,手机号,用户名等都可以创建唯一索引。
(3)单值索引:允许被索引列的数据重复,性能比唯一索引,主键索引要差。
(4)复合索引:复合索引和单值索引的区别就是一个复合索引可以包含多个列。

D23、【初级】哪些字段适合做索引?

(1)频繁作为查询条件且过滤性好的字段应该创建索引。
(2)查询中与其它表关联的字段,关联字段上建立索引。
(3)排序、分组查询、排序字段、分组字段建议加索引。
(4)单键/复合索引的选择问题, 复合索引性价比更高;

D25、【中级】说说你对复合索引的最左匹配原则的理解?

(1)查询条件中必须要包含最左侧的索引列。
(2)查询条件中索引列要连续,中间不能断开。

D26、【高级】说说你对索引回表的理解?

(1)B+ tree索引主要可以分为两种索引,聚集索引和非聚集索引。
(2)聚集索引:也就是平常我们说的主键索引,在 B+ 树中叶子节点存的是整行数据。
(3)非聚集索引:也叫二级索引,也就是一般的普通索引,在 B+ 树中叶子节点存的是主键的值。
(4)我们如果直接用主键查找,用的是聚集索引,能找到全部的数据。
(5)如果我们是用非聚集索引查找,如果索引里不包含全部要查找的字段,则需要根据索引叶子节点存的主键值,再到聚集索引里查找需要的字段,这个过程也叫做回表。

D27、【高级】说说B-tree和B+tree有什么区别?

(1)btree是为了磁盘或其它存储设备而设计的一种多叉平衡查找树(相对于二叉,btree每个内结点有多个分支,即多叉),而b+tree是btree的一个变种,是b+tree在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引。
(2)btree的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;b+tree的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。
(3)在btree中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而b+tree中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。

D28、【高级】什么是索引回表,如何避免?

(1)回表:先定位【主键值】,再定位【行记录】,扫描了两次B+树,这就是回表。
(2)避免方法:用覆盖索引可以避免回表。将被查询的字段,建立到联合索引里去。

D30、MySQL死锁产生的原因和解决方法是什么?

产生原因
当多个事务同时持有和请求同一资源上的锁而产生循环依赖的时候就产生了死锁。死锁发生在事务试图以不同的顺序锁定资源。以StockPrice表上的两个事务为例:(看下图)

如果不走运的话,每个事务都可以执行完第一个语句,并在过程中锁住资源。然后每个事务都试图去执行第二行语句,当时却发现它被锁住了。两个事务将永远的等待对方完成,除非有其他原因打断死锁。

解决方案
(1)使用更小的事务,尽量避免死锁
(2)修改事务的隔离级别
(3)使用更少的锁定。如果你可以接受允许一个SELECT从一个旧的快照返回数据,不要给它添加FOR UPDATE或LOCK IN SHARE MODE子句。

4444 Redis缓存问题======================================

R1、【初级】Redis常用的数据类型有哪些?

(1)String(字符串)
(2)Hash(哈希)
(3)List(列表)
(4)Set(集合)
(5)zset(sorted set:有序集合)

它还有三种特殊的数据结构类型(了解)
Geospatial
Hyperloglog
Bitmap

R2、redis的持久化方式有几种,项目中怎么选择?

(1)RDB:全量备份,节省磁盘空间,恢复速度快。但是可能会丢失数据。
(2)AOF:日志增量备份,数据保存完整。但是整体的恢复效率低,占空间。
(3)如果数据比较敏感的情况下,建议两个都开启。如果只是做纯缓存,数据不敏感,可以都不开启。
(4)默认开启的时RDB,通常使用默认就行,对于一些数据敏感的场景全部开启,不建议单独使用AOF,AOF在高频读写情况下可能会出现bug。

R3、如果想在redis里面存储一个Java对象,能存吗?

(1)可以存储,项目中使用的redisTemplate默认的是将Vule值序列化后存储到redis。
(2)也可以将Java对象转成json字符串存储到redis。

R4、RedisTemplate和StringRedisTemplate区别?

(1)StringRedisTemplate继承了RedisTemplate但是两者的数据不能共用,RedisTemplate存储的数据只能通过RedisTemplate获取。
(2)StringRedisTemplate和RedisTemplate最大的区别就是默认采用的序列化策略不同,StringRedisTemplate默认的是String序列化,RedisTemplate默认使用的是JDK的序列化方式。
(3)StringRedisTemplate存储效率比RedisTemplate高,同时存储占用空间小。但是不如RedisTemplate灵活方便。当操作的数据是复杂的Java对象而不想做任何数据类型转换的时候那么建议使用RedisTemplate

R5、如何保证redis中存放的都是热点数据?

(1)设置redis的最大存储空间,建议设置为服务器内存的3/4。
(2)设置redis的内存淘汰策略,设置为volatile-lru或allkeys-lru。
(3)到达redis的最大值触发内存淘汰机制:
- volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。
- allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰)

R6、什么是缓存击穿?

是针对缓存中没有但数据库有的数据。场景是,当一个热Key失效后,假如瞬间突然涌入大量的请求,来请求同一个Key,这些请求不会命中Redis,都会请求到DB,导致数据库压力过大,甚至扛不住,挂掉。

R7、什么是Redis的缓存雪崩?

(1)是指大量的热Key同时失效,对这些Key的请求就会瞬间打到DB上,同样会导致数据库压力过大甚至挂掉。
(2)解决方案:
- 设置KEY永不过期,但缺点是占用大量内存
- 设置KEY的过期时间为一个随机值,这样就能够防止大量的热KEY同时过期

R8、什么是缓存穿透?

(1)Redis缓存穿透指的是,在Redis缓存和数据库中都找不到相关的数据。也就是说这是个非法的查询,客户端发出了大量非法的查询 比如id是负的 ,导致每次这个查询都需要去Redis和数据库中查询。导致MySql直接爆炸!
(2)解决方案:
- 缓存空对象:如果他的查询数据是合法的,但是确实Redis和MySql中都没有,那么我们就在Redis中储存一个空对象,这样下次客户端继续查询的时候就能在Redis中返回了。但是,如果客户端一直发送这种恶意查询,就会导致Redis中有很多这种空对象,浪费很多空间
- 布隆过滤器:当我们想新增一个元素时(例如新增python),布隆过滤器就会使用hash函数计算出几个索引值,然后将二进制数组中对应的位置修改为1。

R9、缓存击穿、缓存穿透、缓存雪崩的解决方案是什么?

R11、Redis 是单进程单线程的吗?

(1)Redis 在设计上采用将网络数据读写和协议解析通过多线程的方式来处理,对于命令执行来说,仍然使用单线程操作。
(2)从Redis6 版本开始,已经引入了多线程。

R14、Redis 内存淘汰策略有哪些?

1.noeviction(默认策略):对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外)
2.allkeys-lru:从所有key中使用LRU算法进行淘汰(LRU算法:即最近最少使用算法)
3.volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰
4.allkeys-random:从所有key中随机淘汰数据
5.volatile-random:从设置了过期时间的key中随机淘汰
6.volatile-ttl:在设置了过期时间的key中,淘汰过期时间剩余最短的
当使用volatile-lru、volatile-random、volatile-ttl这三种策略时,如果没有key可以被淘汰,则和noeviction一样返回错误

R16、Redis的主从全量同步流程能说说吗?

(1)slave节点请求增量同步
(2)master节点判断replid,发现不一致,拒绝增量同步,使用全量同步
(3)master将完整数据生成RDB,发送RDB到slave
(4)slave清空本地数据,加载RDB文件
(5)master将RDB期间产生的命令记录在repl_baklog,并持续性的将repl_baklog发送到slave
(6)slave接收到这些命令,保持与master数据同步。

R17、Redis的主从增量同步流程能说说吗?

(1)slave节点请求增量同步
(2)master节点判断replid,如果一致返回continue
(3)从repl_baklog中获取增量数据
(4)发送offset后面的命令
repl_baklog的容量是有上线的,写满后会覆盖最早的数据。如果slave断开的时间太久,导致尚未备份的数据被覆盖(offset会标记repl_baklog中备份的数据),就无法做增量同步,只能去做全量同步。

R19、如果Redis服务崩溃了怎么办?

(1)给Redis设置持久化,这样服务器重启能够快速恢复到工作状态。
(2)搭建Redis集群实现高可用。

R20、你知道怎么实现Redis的高可用吗?

我们在项目中使用Redis,肯定不会是单点部署Redis服务的。因为,单点部署一旦宕机,就不可用了。为了实现高可用,通常的做法是,将数据库复制多个副本以部署在不同的服务器上,其中一台挂了也可以继续提供服务。
Redis 实现高可用有三种部署模式:
- 主从模式
- 哨兵模式
- 集群模式。

R21、说说你对Redis哨兵模式的理解?

主从模式中,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址。显然,多数业务场景都不能接受这种故障处理方式。Redis从2.8开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。

哨兵模式,由一个或多个Sentinel实例组成的Sentinel系统,它可以监视所有的Redis主节点和从节点,并在被监视的主节点进入下线状态时,自动将下线主服务器属下的某个从节点升级为新的主节点。但是呢,一个哨兵进程对Redis节点进行监控,就可能会出现问题(单点问题),因此,可以使用多个哨兵来进行监控Redis节点,并且各个哨兵之间还会进行监控。

R22、Redis哨兵模式的作用是什么?

简单来说,哨兵模式就三个作用:
(1)发送命令,等待Redis服务器(包括主服务器和从服务器)返回监控其运行状态;
(2)哨兵监测到主节点宕机,会自动将从节点切换成主节点,然后通过发布订阅模式通知其他的从节点,修改配置文件,让它们切换主机;
(3)哨兵之间还会相互监控,从而达到高可用。

R24、Redis的Cluster集群模式解决了什么问题?

哨兵模式基于主从模式,实现读写分离,它还可以自动切换,系统可用性更高。但是它每个节点存储的数据是一样的,浪费内存,并且不好在线扩容。因此,Cluster集群应运而生,它在Redis3.0加入的,实现了Redis的分布式存储。对数据进行分片,也就是说每台Redis节点上存储不同的内容,来解决在线扩容的问题。并且,它也提供复制和故障转移的功能。

R26、能说说Redis分布式集群是如何存储数据的吗?

Hash Slot插槽算法

既然是分布式存储,Cluster集群使用的分布式算法是一致性Hash嘛?并不是,而是Hash Slot插槽算法。

插槽算法把整个数据库被分为16384个slot(槽),每个进入Redis的键值对,根据key进行散列,分配到这16384插槽中的一个。使用的哈希映射也比较简单,用CRC16算法计算出一个16 位的值,再对16384取模。数据库中的每个键都属于这16384个槽的其中一个,集群中的每个节点都可以处理这16384个槽。

集群中的每个节点负责一部分的hash槽,比如当前集群有A、B、C个节点,每个节点上的哈希槽数 =16384/3,那么就有:

节点A负责0~5460号哈希槽
节点B负责5461~10922号哈希槽
节点C负责10923~16383号哈希槽

5555Spring框架面试题======================================

F1、类的反射机制有啥用?

(1)增加程序的灵活性,可扩展性,动态创建对象。
(2)框架必备,任何框架的封装都要用反射。(框架的灵魂)

F2、获取Class对象的三种方式?

(1)Class.forName();
(2)类名.class;
(3)对象.getClass();

F3、Java创建对象的方式有哪些?

(1)new 关键字。
(2)使用类的反射机制
(3)使用类的clone
(4)采用反序列化机制

F4、对于IOC你是怎么理解的?

IoC(Inversion of Control)翻译过来是控制翻转,是一种设计思想,将创建对象的权力交给spring容器去控制,用来创建和管理bean
(1)改变了创建对象的方式和获取资源的方式
容器控制应用程序的对象创建,实例化,和对象之间的依赖
程序不能主动获取外部资源了,而是ioc容器给他注入,

F5、讲解你对Spring依赖注入的理解?

(1)因为程序需要运行这些外部资源,所以依赖注入就是给对象中的属性赋值

F7、Spring对象常用的注入方式(DI)?

(1)setter注入
(2)构造方法注入
(3)基于注解的方式注入

F8、@Autowired 与@Resource?

(1)相同点:
@Autowired和@Resource功能相同,都可以用来装配bean;
两个注解可以加载属性字段或写在setter方法上;
(2)不同点:
提供方不同:@Autowired是Spring框架提供,@Resource是Jdk自带
装配方式不同:
@Autowired默认按照byType装配;
@Resource默认按照byName装配,如果匹配不到,则继续使用byType装配;

F9、Spring Bean的作用域?

当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:

singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例

prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例

request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效

session:对于每次HTTP Session,使用session定义的Bean都将产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效

globalSession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效

F10、BeanFactory和FactoryBean的区别?

(1)BeanFactory:是一个工厂,IOC的顶级接口,用来管理和获取Bean对象。
(2)FactoryBean:是一个Bean生成工具,是用来获取一种类型对象的Bean,它是构造Bean实例的一种方式。用户可以通过实现该接口定制实例化 Bean 的逻辑。

F11、bean生命周期有哪些?

Bean定义
实例化
属性赋值
初始化
生存期
销毁

F13、Spring如何解决循环依赖问题?

Spring是通过三级缓存机制来解决Bean创建的循环依赖问题的,具体如下:
(1)一级缓存,singletonObjects,存储所有已创建完毕的单例 Bean (完整的 Bean)。
(2)二级缓存,earlySingletonObjects,存储所有仅完成实例化,但还未进行属性注入和初始化的 Bean。
(3)三级缓存,singletonFactories,存储能建立这个 Bean 的一个工厂,通过工厂能获取这个 Bean,延迟化 Bean 的生成,工厂生成的 Bean 会塞入二级缓存。

具体流程如下:
(1)A创建过程中需要B,于是A将自己放到三级缓存里面,去实例化B
(2)B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A然后把三级缓存里面的这个A放到二级缓存里面,并删除三级缓存里面的A
(3)B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建,并将A放到一级缓存中。

AOP

F14、什么是AOP?

面向切面编程,一种编程思想,在不改变原有的逻辑的基础上,增加一些额外的功能。

F15、AOP的应用场景有哪些?

(1)权限验证
(2)日志跟踪
(3)事务
(4)读写分离

F16、AOP的通知方式有哪些?

(1)前置通知:在我们执行目标方法之前运行(@Before)
(2)后置通知:在我们目标方法运行结束之后,不管有没有异常(@After)
(3)返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)
(4)异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)
(5)环绕通知:非常灵活,目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,joinPoint.procced()就是执行目标方法的代码 。环绕通知可以控制返回对象(@Around)

F17、AOP底层的实现原理?

AOP底层是通过动态代理实现,两种实现方式:
(1)jdk动态代理:如果目标对象实现了接口,spring默认会使用jdk动态代理实现。
(2)cglib动态代理:如果目标对象没有实现接口,spring默认使用cglib代理实现。
可以强制使用cglib

F18、jdk动态代理和cglib动态代理区别?

(1)jdk动态代理只能对实现了接口的类生成代理,而不能针对类。cglib是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法(继承)。

(2)在低版本的jdk(jdk1.7之前),cglib代理的效率要比jdk动态代理的效率高。在jdk1.7,1.8及之后的版本对jdk动态代理做了优化,jdk动态代理效率要高于cglib代理。

F19、SpringMVC常用注解有哪些?

(1)@Controller和@RestController
(2)@RequestMapping
(3)@PathVariable
(4)@RequestParam
(5)@RequestBody
(5)@ResponseBody

F28、Spring bean自动装配有哪些方式?

(1)no - 这是默认设置,表示没有自动装配。应使用显式 bean 引用进行装配。
(2)byName - 它根据 bean 的名称注入对象依赖项。它匹配并装配其属性与 XML文件中由相同名称定义的 bean。
(3)byType - 它根据类型注入对象依赖项。如果属性的类型与 XML 文件中的一个 bean 名称匹配,则匹配并装配属性。
(4)构造函数- 它通过调用类的构造函数来注入依赖项。它有大量的参数。
(5)autodetect - 首先容器尝试通过构造函数使用 autowire 装配,如果不能,则尝试通过 byType 自动装配。

F29、Spring 框架中都用到了哪些设计模式?

工厂模式:BeanFactory就是简单工厂模式的体现,用来创建对象的实例;
单例模式:Bean默认为单例模式。
代理模式:Spring的AOP功能用到了JDK的动态代理和CGLIB字节码生成技术;
模板方法:用来解决代码重复的问题。比如. RestTemplate, JmsTemplate, JpaTemplate。
观察者模式:定义对象键一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知被制动更新

F30、Spring基于xml注入bean的几种方式

Set方法注入;
构造器注入:
静态工厂注入;
实例工厂;

F36、@Component, @Controller, @Repository, @Service 有何区别?

@Component:这将 java 类标记为 bean。它是任何 Spring 管理组件的通用构造型。spring 的组件扫描机制现在可以将其拾取并将其拉入应用程序环境中。

@Controller:这将一个类标记为 Spring Web MVC 控制器。标有它的 Bean 会自动导入到 IoC 容器中。

@Service:此注解是组件注解的特化。它不会对 @Component 注解提供任何其他行为。您可以在服务层类中使用 @Service 而不是 @Component,因为它以更好的方式指定了意图。

@Repository:这个注解是具有类似用途和功能的 @Component 注解的特化。它为 DAO 提供了额外的好处。它将 DAO 导入 IoC 容器,并使未经检查的异常有资格转换为 Spring DataAccessException。

42、说一下Spring的事务传播行为

(1)如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
(2)支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。
(3)支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
(4)创建新事务,无论当前存不存在事务,都创建新事务。
(5)以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
(6)以非事务方式执行,如果当前存在事务,则抛出异常。
(7)如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。

6666 微服务框架面试题======================================

S1、集群与分布式有啥区别?

(1)相同点:
分布式和集群都是需要有很多节点服务器通过网络协同工作完成整体的任务目标。
(2)不同点:
分布式是指将业务系统进行拆分,即分布式的每一个节点都是实现不同的功能。而集群每个节点做的是同一件事情。

S2、什么是微服务?

能够独立部署,运行,提供功能的系统服务。
(2)思想:
大的系统模块拆分成一个个的小功能模块,独立部署,共同组合成一个大的系统。
微服务是一种特殊的分布式架构,架构思想相同,微服务的拆分力度更细,可以说微服务架构是分布式架构的子集。
(3)优点:
- 灵活,扩展性极强。
- 易于协同开发,责任划分明确。
- 符合“高内聚,低耦合” 的编程思想。
- 不受技术栈限制,方便系统迭代。

(4)缺点
- 运维成本增加。(容器docker)
- 跟踪问题复杂了。(统一的日志,链路追踪)

S5、微服务的拆分原则

(1)维度:时间,空间,成本,地域,业务….
(2)简单实用:横向提取,纵向切割。
横向(水平):将系统中公共独立的功能提取出来。
纵向(垂直):将系统按照业务功能模块切分,每个模块就是一个微服务。

S6、远程调用中RESTful和RPC有啥区别?

(1)目前主流的远程调用技术有基于HTTP的RESTful接口以及基于TCP的RPC协议。
(2)RESTful通讯协议HTTP,经常写的RestController就是RESTful风格,特点是比较灵活,通常用于微服务架构。
(3)RPC通讯协议一般使用TCP,性能较好,不如RESTful灵活,通常用于SOA架构。

S7、RestTemplate有啥用?

Spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。

S8、说说你对CAP理论的理解?

特点
(1)Consistency(一致性)
数据一致更新,所有数据的变化都是同步的
(2)Availability(可用性)
在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求
(3)Partition tolerance(分区容忍性)

原理
(1)CAP目标:某个节点的故障,并不影响整个系统的运行
(2)CAP原理:任何分布式系统只可同时满足二点,没法三者兼顾,既然一个分布式系统无法同时满足一致性、可用性、分区容错性三个特点, 所以我们就需要抛弃一样;

S9、SpringCloud有哪些常用组件?

(1)Eureka(注册中心)、Nacos
(2)Zuul(网关)、Gateway
(3)Fegin(远程调用)、OpenFeign
(4)Ribbon(负责均衡)
(5)Hystrix(熔断器)

S10、SpringCloud Alibaba组件?

(1)Nacos(配置中心与注册中心)
(2)Sentinel(熔断与限流)
(3)Seata(分布式事务)

S10、服务熔断和服务降级有什么区别?

相同点
(1)目的是一致的:都是从可用性和可靠性出发,为了防止系统崩溃;
(2)用户体验类似:最终都让用户体验到的是某些功能暂时不可用;

不同点
触发原因不同:
(1)服务熔断一般是某个服务(下游服务)故障引起;所以熔断是被动的。
(2)服务降级一般是从整体负荷考虑,并发太大,先保证整体的可用;所以降级是主动。

S11、Zuul和Gateway的区别?

相同点
(1)底层都是servlet
(2)两者均是web网关,处理的是http请求

不同点
(1)内部实现不同

gateway对比zuul多依赖了spring-webflux,在spring的支持下,功能更强大,内部实现了限流、负载均衡等,扩展性也更强,但同时也限制了仅适合于Spring Cloud套件
zuul则可以扩展至其他微服务框架中,其内部没有实现限流、负载均衡等。
(2)是否支持异步

zuul仅支持同步
gateway支持异步。理论上gateway则更适合于提高系统吞吐量(但不一定能有更好的性能),最终性能还需要通过严密的压测来决定

S12、SpringBoot的常用注解有哪些?

@Controller
@RestController
@Service
@RequestMapping
@RequestBody
@PathVariable
@RequestParam
@ResponseBody
@Autowired
@Component
@Bean

7777======================================

R1、RabbitMQ有啥用处?

(1)顺序消费
(2)定时任务
(3)请求削峰
(4)服务间异步通信

R2、RabbitMQ有哪些常用的工作模式?六种工作模式(了解)

工作模式(Work)
发布订阅模式(Fanout)
路由模式(Routing)
主题模式(Topic)

R3、如何保证RabbitMQ消息不被重复消费?

通过消费端处理,每条消息分配唯一的id,消费端在消费的时候验证,过滤掉重复的消息。
使用乐观锁实现,保证接口的幂等性。

R4、如何保证RabbitMQ消息的可靠传输?

发送端:
(1)开启Confirm模式(消息确认机制或者事务模式)。
(2)如果消息发送失败做补偿处理,记录日志重新发送等,确保消息最终发送成功。

队列:
(1)声明交换机,队列的时候设置持久化参数。
(2)发送消息的时候设置消息的持久化参数,队列消息持久化到磁盘上,即便是宕机,重启之后消息依旧还在。

接收端:
(1)接收端开启手动应答模式。
(2)确定消息处理完成,消费端再向队列确认消费,删除消息。
(3)消费端如果处理异常,记录日志,通过其他补偿机制处理,确保最终消息处理成功。

R5、RabbitMQ的交换机有哪些类型?

Direct Exchange:直连交换机,根据Routing Key(路由键)进行投递到不同队列。
Fanout Exchange:扇形交换机,采用广播模式,根据绑定的交换机,路由到与之对应的所有队列。
Topic Exchange:主题交换机,对路由键进行模式匹配后进行投递,符号#表示一个或多个词,*表示一个词。
Header Exchange:头交换机,不处理路由键。而是根据发送的消息内容中的headers属性进行匹配。

R6、Topic模式时,Routingkey中的#号和*号有什么区别?

#号标识0个字符、1个字符、多个字符
*号表示1个或者多个字符

ElasticSearch面试问题

什么是倒排索引?
倒排索引,倒排索引又叫反向索引(inverted index)。
反向索引
把“文档→单词”的形式变为“单词→文档”的形式。

正向索引
当用户发起查询时(假设查询为一个关键词),搜索引擎会扫描索引库中的所有文档,找出所有包含关键词的文档,这样依次从文档中去查找是否含有关键词的方法叫做正向索引。

Mybatis和MybatisPlus面试问题

M1、Mybatis的一级缓存和二级缓存有什么区别,怎么开启?

(1)区别

一级缓存是SqlSession级别的缓存。在操作数据库时需要构造SqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的SqlSession之间的缓存数据区域(HashMap)是互不影响的。
MyBatis的二级缓存是Application级别的缓存,它可以提高对数据库查询的效率,以提高应用的性能。
Mybatis中,一级缓存默认是开启的。而二级缓存需要手动开启。
(2)开启

开启一级缓存
默认开启,无需特殊处理

开启二级缓存
在yml中添加以下代码:

mybatis:
  configuration:
    cache-enabled: true

M2、#{} 和 ${} 的区别是什么?

两者在 MyBatis 中都可以作为 SQL 的参数占位符,在处理方式上不同

#{}:在解析 SQL 的时候会将其替换成 ? 占位符,然后通过 JDBC 的 PreparedStatement 对象添加参数值,这里会进行预编译处理,可以有效地防止 SQL 注入,提高系统的安全性
${}:在 MyBatis 中带有该占位符的 SQL 片段会被解析成动态 SQL 语句,根据入参直接替换掉这个值,然后执行数据库相关操作,存在 SQL注入 的安全性问题

8888 JVM优化======================================

J01、类加载的几个过程?

加载、验证、准备、解析、初始化。然后是使用和卸载了

J03、java 中垃圾收集的方法有哪些?

标记-清除:
这是垃圾收集算法中最基础的,根据名字就可以知道,它的思想就是标记哪些要被回收的对象,然后统一回收。这种方法很简单,但是会有两个主要问题:
1.效率不高,标记和清除的效率都很低;
2.会产生大量不连续的内存碎片,导致以后程序在分配较大的对象时,由于没有充足的连续内存而提前触发一次 GC 动作。

复制算法:
为了解决效率问题,复制算法将可用内存按容量划分为相等的两部分,然后每次只使用其中的一块,当一块内存用完时,就将还存活的对象复制到第二块内存上,然后一次性清楚完第一块内存,再将第二块上的对象复制到第一块。但是这种方式,内存的代价太高,每次基本上都要浪费一般的内存。

于是将该算法进行了改进,内存区域不再是按照 1:1 去划分,而是将内存划分为8:1:1 三部分,较大那份内存交 Eden 区,其余是两块较小的内存区叫 Survior 区。

每次都会优先使用 Eden 区,若 Eden 区满,就将对象复制到第二块内存区上,然后清除 Eden 区,如果此时存活的对象太多,以至于 Survivor 不够时,会将这些对象通过分配担保机制复制到老年代中。(java 堆又分为新生代和老年代)

标记-整理:
该算法主要是为了解决标记-清除,产生大量内存碎片的问题;当对象存活率较高时,也解决了复制算法的效率问题。它的不同之处就是在清除对象的时候现将可回收对象移动到一端,然后清除掉端边界以外的对象,这样就不会产生内存碎片了。

分代收集:
现在的虚拟机垃圾收集大多采用这种方式,它根据对象的生存周期,将堆分为新生代和老年代。在新生代中,由于对象生存期短,每次回收都会有大量对象死去,那么这时就采用复制算法。老年代里的对象存活率较高,没有额外的空间进行分配担保,所以可以使用标记-整理或者 标记-清除。

J04、什么是类加载器,类加载器有哪些?

实现通过类的权限定名获取该类的二进制字节流的代码块叫做类加载器。

主要有一下四种类加载器:

J05、类加载器双亲委派模型机制?

当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。
优点
(1)系统类防止内存中出现多份同样的字节码
(2)保证Java程序安全稳定运行

J07、怎么打破双亲委派模型?

自定义类加载器,继承ClassLoader类,重写loadClass方法和findClass方法;

J08、什么情况下会发生栈内存溢出?

(1)栈是线程私有的,栈的生命周期和线程一样,每个方法在执行的时候就会创建一个栈帧,它包含局部变量表、操作数栈、动态链接、方法出口等信息,局部变量表又包括基本数据类型和对象的引用;
(2)当线程请求的栈深度超过了虚拟机允许的最大深度时,会抛出StackOverFlowError异常,方法的递归调用有可能会出现该问题;
(3)调整参数-xss去调整jvm栈的大小

J09、强引用、软应用、弱引用、虚引用的区别?

强引用
强引用是我们使用最广泛的引用,如果一个对象具有强引用,那么垃圾回收期绝对不会回收它,当内存空间不足时,垃圾回收器宁愿抛出OutOfMemoryError,也不会回收具有强引用的对象;我们可以通过显示的将强引用对象置为null,让gc认为该对象不存在引用,从而来回收它;

软引用
软应用是用来描述一些有用但不是必须的对象,在java中用SoftReference来表示,当一个对象只有软应用时,只有当内存不足时,才会回收它;
软引用可以和引用队列联合使用,如果软引用所引用的对象被垃圾回收器所回收了,虚拟机会把这个软引用加入到与之对应的引用队列中;

弱引用
弱引用是用来描述一些可有可无的对象,在java中用WeakReference来表示,在垃圾回收时,一旦发现一个对象只具有软引用的时候,无论当前内存空间是否充足,都会回收掉该对象;
弱引用可以和引用队列联合使用,如果弱引用所引用的对象被垃圾回收了,虚拟机会将该对象的引用加入到与之关联的引用队列中;

虚引用
虚引用就是一种可有可无的引用,无法用来表示对象的生命周期,任何时候都可能被回收,虚引用主要使用来跟踪对象被垃圾回收的活动,虚引用和软引用与弱引用的区别在于:虚引用必须和引用队列联合使用;在进行垃圾回收的时候,如果发现一个对象只有虚引用,那么就会将这个对象的引用加入到与之关联的引用队列中,程序可以通过发现一个引用队列中是否已经加入了虚引用,来了解被引用的对象是否需要被进行垃圾回收;

J10、GC 是什么?为什么要有 GC?

GC 是垃 圾收 集的 意思 ,内存 处理 是编 程人 员容 易出 现问 题的 地方 ,忘记 或者 错误的内 存回 收会 导致 程序 或系 统的 不稳 定甚 至崩 溃, Java 提供 的 GC 功能 可以 自动监测 对象 是否 超过 作用 域从 而达 到自 动回 收内 存的 目的 ,Java 语言 没有 提供 释放已分配内存的 显示 操作 方法 。Java 程序 员不 用担 心内 存管 理, 因为 垃圾 收集 器会自动 进行 管理 。要 请求 垃圾 收集 ,可 以调 用下 面的 方法 之一 :System.gc() 或Runtime.getRuntime().gc() ,但 JVM 可以 屏蔽 掉线 示的 垃圾 回收 调用 。

垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在 Java 诞生初期,垃圾回收是 Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今 Java 的垃圾回收机制已经成为被诟病的东。移动智能终端用户通常觉得 iOS 的系统比 Android 系统有更好的用户体验,其中一个深层次的原因就在于 Android 系统中垃圾回收的不可预知性。

J11、MinorGC,MajorGC、FullGC都什么时候发生?

MinorGC在年轻代空间不足的时候发生,MajorGC指的是老年代的GC,出现MajorGC一般经常伴有MinorGC。

FullGC有三种情况。
1、 当老年代无法再分配内存的时候
2、 元空间不足的时候
3、 显示调用System.gc的时候。另外,像CMS一类的垃圾回收器,在MinorGC出现promotion failure的时候也会发生FullGC

J13、JVM 年轻代到年老代的晋升过程的判断条件是什么呢?

1、 部分对象会在From和To区域中复制来复制去,如此交换15次(由JVM参数MaxTenuringThreshold决定,这个参数默认是15),最终如果还是存活,就存入到老年代。

2、 如果对象的大小大于Eden的二分之一会直接分配在old,如果old也分配不下,会做一次majorGC,如果小于eden的一半但是没有足够的空间,就进行minorgc也就是新生代GC。

3、 minor gc后,survivor仍然放不下,则放到老年代

4、 动态年龄判断 ,大于等于某个年龄的对象超过了survivor空间一半 ,大于等于某个年龄的对象直接进入老年代

J14、JVM 数据运行区,哪些会造成 OOM 的情况?

除了数据运行区,其他区域均有可能造成 OOM 的情况。

堆溢出: java.lang.OutOfMemoryError: Java heap space
栈溢出: java.lang.StackOverflowError
永久代溢出: java.lang.OutOfMemoryError: PermGen space

J15、什么是堆?

存放对象实例,所有的对象和数组都要在堆上分配。 是 JVM 所管理的内存中最大的一块区域。

J16、什么是程序计数器

当前线程所执行的行号指示器。是 JVM 内存区域最小的一块区域。执行字节码工作时就是利用程序计数器来选取下一条需要执行的字节码指令。

J17、各种回收器,各自优缺点,重点讲解CMS、G1?

1、 Serial收集器,串行收集器是最古老,最稳定以及效率高的收集器,但可能会产生较长的停顿,只使用一个线程去回收。
2、 ParNew收集器,ParNew收集器其实就是Serial收集器的多线程版本。
3、 Parallel收集器,Parallel Scavenge收集器类似ParNew收集器,Parallel收集器更关注系统的吞吐量。
4、 Parallel Old收集器,Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程“标记-整理”算法
5、 CMS收集器,CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它需要消耗额外的CPU和内存资源,在CPU和内存资源紧张,CPU较少时,会加重系统负担。CMS无法处理浮动垃圾。CMS的“标记-清除”算法,会导致大量空间碎片的产生。
6、 G1收集器,G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器、以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征。

J18、类的实例化顺序?

比如父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行顺序
先静态、先父后子。
先静态:父静态 > 子静态
优先级:父类 > 子类 静态代码块 > 非静态代码块 > 构造函数

一个类的实例化过程:

1、 父类中的static代码块,当前类的static
2、 顺序执行父类的普通代码块
3、 父类的构造函数
4、 子类普通代码块
5、 子类(当前类)的构造函数,按顺序执行。
6、 子类方法的执行,

J19、Serial 与 Parallel GC 之间的不同之处?

Serial 与 Parallel 在 GC 执行的时候都会引起 stop-the-world。它们之间主要不同 serial 收集器是默认的复制收集器,执行 GC 的时候只有一个线程,而parallel 收集器使用多个 GC 线程来执行。

J20、JVM 提供的常用工具有哪些?

jps:
用来显示本地的 Java 进程,可以查看本地运行着几个 Java 程序,并显示他们的进程号。 命令格式:jps

jinfo:
运行环境参数:Java System 属性和 JVM 命令行参数,Java class path 等信息。 命令格式:jinfo 进程 pid

jstat:
监视虚拟机各种运行状态信息的命令行工具。 命令格式:jstat -gc 123 250 20

jstack:
可以观察到 JVM 中当前所有线程的运行情况和线程当前状态。 命令格式:jstack 进程 pid

jmap:
观察运行中的 JVM 物理内存的占用情况(如:产生哪些对象,及其数量)。 命令格式:jmap [option] pid

J22、对象都是优先分配在年轻代上的吗?

不是。当新生代内存不够时,老年代分配担保。而大对象则是直接在老年代分配

J24、你知道哪些JVM性能调优?

设定堆内存大小

1、 -Xmx:堆内存最大限制。设定新生代大小。新生代不宜太小,否则会有大量对象涌入老年代
2、 -XX:NewSize:新生代大小
3、 -XX:NewRatio 新生代和老生代占比
4、 -XX:SurvivorRatio:伊甸园空间和幸存者空间的占比
5、 设定垃圾回收器 年轻代用 -XX:+UseParNewGC 年老代用-XX:+UseConcMarkSweepGC