Skip to content

Commit b9e246d

Browse files
committed
增加消息队列面试题
1 parent 76efb6e commit b9e246d

File tree

4 files changed

+57
-28
lines changed

4 files changed

+57
-28
lines changed

Java/Java基础面试题.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ equals与hashcode的关系:
567567

568568
hashcode方法主要是用来**提升对象比较的效率**,先进行hashcode()的比较,如果不相同,那就不必在进行equals的比较,这样就大大减少了equals比较的次数,当比较对象的数量很大的时候能提升效率。
569569

570-
之所以重写equals()要重写hashcode(),是为了保证equals()方法返回true的情况下hashcode值也要一致,如果重写了equals()没有重写hashcode(),就会出现两个对象相等但hashcode()不相等的情况。这样,当用其中的一个对象作为键保存到hashMap、hashTable或hashSet中,再以另一个对象作为键值去查找他们的时候,则会查找不到。
570+
之所以重写`equals()`要重写`hashcode()`,是为了保证`equals()`方法返回true的情况下hashcode值也要一致,如果重写了`equals()`没有重写`hashcode()`,就会出现两个对象相等但`hashcode()`不相等的情况。这样,当用其中的一个对象作为键保存到hashMap、hashTable或hashSet中,再以另一个对象作为键值去查找他们的时候,则会查找不到。
571571

572572
## Java创建对象有几种方式?
573573

@@ -641,7 +641,7 @@ public class LifeCycle {
641641

642642
- 对于基本数据类型,==比较的是他们的值。基本数据类型没有equal方法;
643643

644-
- 对于复合数据类型,==比较的是它们的存放地址(是否是同一个对象)。equals()默认比较地址值,重写的话按照重写逻辑去比较。
644+
- 对于复合数据类型,==比较的是它们的存放地址(是否是同一个对象)。`equals()`默认比较地址值,重写的话按照重写逻辑去比较。
645645

646646
## 常见的关键字有哪些?
647647

@@ -879,14 +879,14 @@ public class Student extends Person {
879879

880880
## 接口与抽象类区别?
881881

882-
1、语法层面上
882+
1、**语法层面**上的区别
883883

884884
- 抽象类可以有方法实现,而接口的方法中只能是抽象方法;
885885
- 抽象类中的成员变量可以是各种类型的,接口中的成员变量只能是public static final类型;
886886
- 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
887887
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
888888

889-
2、设计层面上的区别
889+
2、**设计层面**上的区别
890890

891891
- 抽象层次不同。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口只是对类行为进行抽象。继承抽象类是一种"是不是"的关系,而接口实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是具备不具备的关系,比如鸟是否能飞。
892892
- 继承抽象类的是具有相似特点的类,而实现接口的却可以不同的类。
@@ -907,24 +907,24 @@ class BMWCar extends Car implements Alarm {
907907

908908
常见的RuntimeException:
909909

910-
1. ClassCastException //类型转换异常
911-
2. IndexOutOfBoundsException //数组越界异常
912-
3. NullPointerException //空指针
913-
4. ArrayStoreException //数组存储异常
914-
5. NumberFormatException //数字格式化异常
915-
6. ArithmeticException //数学运算异常
910+
1. `ClassCastException` //类型转换异常
911+
2. `IndexOutOfBoundsException` //数组越界异常
912+
3. `NullPointerException` //空指针
913+
4. `ArrayStoreException` //数组存储异常
914+
5. `NumberFormatException` //数字格式化异常
915+
6. `ArithmeticException` //数学运算异常
916916

917917
unchecked Exception:
918918

919-
1. NoSuchFieldException //反射异常,没有对应的字段
920-
2. ClassNotFoundException //类没有找到异常
921-
3. IllegalAccessException //安全权限异常,可能是反射时调用了private方法
919+
1. `NoSuchFieldException` //反射异常,没有对应的字段
920+
2. `ClassNotFoundException` //类没有找到异常
921+
3. `IllegalAccessException` //安全权限异常,可能是反射时调用了private方法
922922

923923
## Error和Exception的区别?
924924

925-
Error:JVM 无法解决的严重问题,如栈溢出`StackOverflowError`、内存溢出`OOM`等。程序无法处理的错误。
925+
**Error**:JVM 无法解决的严重问题,如栈溢出`StackOverflowError`、内存溢出`OOM`等。程序无法处理的错误。
926926

927-
Exception:其它因编程错误或偶然的外在因素导致的一般性问题。可以在代码中进行处理。如:空指针异常、数组下标越界等。
927+
**Exception**:其它因编程错误或偶然的外在因素导致的一般性问题。可以在代码中进行处理。如:空指针异常、数组下标越界等。
928928

929929
## 运行时异常和非运行时异常(checked)的区别?
930930

@@ -941,11 +941,11 @@ Exception:其它因编程错误或偶然的外在因素导致的一般性问
941941

942942
## BIO/NIO/AIO区别的区别?
943943

944-
同步阻塞IO : 用户进程发起一个IO操作以后,必须等待IO操作的真正完成后,才能继续运行。
944+
**同步阻塞IO** : 用户进程发起一个IO操作以后,必须等待IO操作的真正完成后,才能继续运行。
945945

946-
同步非阻塞IO: 客户端与服务器通过Channel连接,采用多路复用器轮询注册的`Channel`。提高吞吐量和可靠性。用户进程发起一个IO操作以后,可做其它事情,但用户进程需要轮询IO操作是否完成,这样造成不必要的CPU资源浪费。
946+
**同步非阻塞IO**: 客户端与服务器通过Channel连接,采用多路复用器轮询注册的`Channel`。提高吞吐量和可靠性。用户进程发起一个IO操作以后,可做其它事情,但用户进程需要轮询IO操作是否完成,这样造成不必要的CPU资源浪费。
947947

948-
异步非阻塞IO: 非阻塞异步通信模式,NIO的升级版,采用异步通道实现异步通信,其read和write方法均是异步方法。用户进程发起一个IO操作,然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知。类似Future模式。
948+
**异步非阻塞IO**: 非阻塞异步通信模式,NIO的升级版,采用异步通道实现异步通信,其read和write方法均是异步方法。用户进程发起一个IO操作,然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知。类似Future模式。
949949

950950
## 守护线程是什么?
951951

@@ -1036,6 +1036,6 @@ if (obj instanceof String) {
10361036

10371037
1. JDBC连接数据库时使用`Class.forName()`通过反射加载数据库的驱动程序
10381038
2. Eclispe、IDEA等开发工具利用反射动态解析对象的类型与结构,动态提示对象的属性和方法
1039-
3. Web服务器中利用反射调用了Sevlet的service方法
1040-
4. Spring AOP的特性也是依赖反射实现的
1039+
3. Web服务器中利用反射调用了Sevlet的`service`方法
1040+
4. JDK动态代理底层依赖反射实现
10411041

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
## RabbitMQ
129129

130130
1. [RabbitMQ核心知识总结](中间件/RabbitMQ.md) (推荐 :+1:)
131+
1. [消息队列面试题](中间件/消息队列面试题.md)
131132
2. [死信队列](中间件/死信队列.md)
132133

133134
# 计算机网络

中间件/RabbitMQ.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -433,11 +433,3 @@ msg.getMessageProperties().setExpiration("3000");
433433
[线上rabbitmq问题](https://juejin.im/post/6844904088212094983#heading-0)
434434

435435

436-
437-
> 最后给大家分享一个github仓库,上面放了**200多本经典的计算机书籍**,包括C语言、C++、Java、Python、前端、数据库、操作系统、计算机网络、数据结构和算法、机器学习、编程人生等,可以star一下,下次找书直接在上面搜索,仓库持续更新中~
438-
>
439-
> github地址:https://github.com/Tyson0314/java-books
440-
>
441-
> 如果github访问不了,可以访问gitee仓库。
442-
>
443-
> gitee地址:https://gitee.com/tysondai/java-books

中间件/消息队列面试题.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
## 为什么要使用消息队列?
2+
3+
总结一下,主要三点原因:**解耦、异步、削峰**
4+
5+
1、解耦。比如,用户下单后,订单系统需要通知库存系统,假如库存系统无法访问,则订单减库存将失败,从而导致订单操作失败。订单系统与库存系统耦合,这个时候如果使用消息队列,可以返回给用户成功,先把消息持久化,等库存系统恢复后,就可以正常消费减去库存了。
6+
7+
2、异步。将消息写入消息队列,非必要的业务逻辑以异步的方式运行,不影响主流程业务。
8+
9+
3、削峰。消费端慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是允许的。比如秒杀活动,一般会因为流量过大,从而导致流量暴增,应用挂掉。这个时候加上消息队列,服务器接收到用户的请求后,首先写入消息队列,如果消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。
10+
11+
## 使用了消息队列会有什么缺点
12+
13+
- 系统可用性降低。引入消息队列之后,如果消息队列挂了,可能会影响到业务系统的可用性。
14+
- 系统复杂性增加。加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。
15+
16+
## RabbitMQ消息怎么路由?
17+
18+
消息路由必须有三部分:**交换器、路由、绑定**。生产者把消息发布到交换器上;绑定决定了消息如何从路由器路由到特定的队列;消息最终到达队列,并被消费者接收。
19+
20+
1、消息发布到交换器时,消息将拥有一个路由键(routing key),在消息创建时设定。
21+
22+
2、通过队列路由键,可以把队列绑定到交换器上。
23+
24+
3、消息到达交换器后,RabbitMQ会将消息的路由键与队列的路由键进行匹配(针对不同的交换器有不同的路由规则)。如果能够匹配到队列,则消息会投递到相应队列中。
25+
26+
## RabbitMQ如何保证消息的顺序性?
27+
28+
当生产者只有1个,消费者有多个,每个consumer依次从mq中拿数据取数据消费,这种时候,即使mq中的消息不乱序,但由于消费者处理消息的速度不同,最终产生结果的顺序会不同(比如消费者逻辑是插入数据到数据库)
29+
30+
解决办法: 保证顺序的消息都放到1个queue里,同时只被1个消费者消费。
31+
32+
## 如何避免消息重复消费?
33+
34+
在消息生产时,MQ内部针对每条生产者发送的消息生成一个唯一id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列。
35+
36+
在消息消费时,要求消息体中也要有一全局唯一id作为去重和幂等的依据,避免同一条消息被重复消费。

0 commit comments

Comments
 (0)