大家好,我是一个骚与帅并重的男人。我一直自学Java到现在,有一些心得在给大家分享面试题前我必须跟大家分享讨论一下!
我在自学的时候我学着学着,突然发现我学会了redis,又去学docker时,之前redis的命令语法以及雪崩,击穿。。。一系列场景我都忘得差不多一干二净了。
于是我就在想,特么的我学了又忘学了又忘,这有啥用?岂不是在做无用功?终于在一个月黑风高,夜深人静的晚上我醒悟了,我觉得我这样子下去是找不到java工作的,面试官其实问的问题跟这些框架中间件的用法可以说是毫无关系。
那么面试官问的问题可就有点东西了,也就是我耗费心血,苦心研究出来的这100道基础面试题,如果说是高级java开发的话请自动绕开,这些个面试题和你没有任何关系了。以下的面试题只适用于初级、中级的开发。
我不敢说这些面试题是最全面的,但我敢说这些面试题都是外面公司面试官有很大几率会问到的
所以说各位小哥哥、小姐姐们接下来就让我们一起来理解透彻这些超级无敌牛皮爆炸上天的面试题吧!
此吊打面试官系列会支持更新,目前版本1.0.0,更新日期2024年2月9日23:33:54!!!
文章末尾关注公众号有惊喜哦!!!
1、什么是面向对象?
答:
面向对象与面向过程有所不同。
面向过程是专门针对性去做某一件事情的,比如说:洗衣服需要打开洗衣机,放入衣服、放入洗衣粉、关闭洗衣机。。。
而面向对象则是什么样的人去操作什么样特征的洗衣机
面向对象优点:更易于复用、扩展、维护
特征:
封装:功能方法只需对外开放api,调用者无需关心这个功能的内部细节是如何实现的
比如:spring框架的getBean获取bean的api就是一个封装
继承:作用就是不同子类都能够使用相同的父类代码,优化了代码,减少了代码重复
多态:基于对象所属类的不同,外部对同一个方法的调用,实际逻辑不同
对功能代码的重新实现
比如:spring的application对象就有很多不同功能的子类,通过配置文件方式来获取bean,或者通过配置类来获取bean
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
2、==与equals的区别?
==是对内存地址的比较
equals其实底层也是对内存地址的比较
只是有些对象对equals方法进行了重写
比如:string的equals方法重写过后就是对每个字符串的值进行比较,而不是去堆或者栈上边去比较内存
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
3、final?
修饰类:此类不能够被继承
修饰方法:此方法不能被重写,但是能够被重载
修饰变量:变量一旦赋值,值则不可再进行修改
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
4、String、StringBuffer、StringBuild区别?
String:不可被修改,替换值其实是在内存重新new了一个string对象
StringBuffer:可以被修改,线程安全,因为所有方法都加了一个悲观锁synchronized
StringBuild:可以被修改,线程不安全,存在并发问题
执行速度:StringBuilder > StringBuffer > String
为啥这样子排序呢?因为String创建新对象消耗内存最高,StringBuffer加了个锁,StringBuilder啥也没有
场景:经常需要改变字符串内容时用什么
优先使用StringBuilder,多线程共享变量时使用StringBuffer
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
5、String 属于基础的数据类型吗?
String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
6、重载和重写的区别?
重载:同一个类中,方法名称相同,方法参数类型、个数、顺序不同
重写:父子类中,方法名称相同,方法参数类型、个数、顺序都相同。子类方法返回值范围小于等于父类,抛出异常范围小于等于父类,访问修饰符大于等于父类。父类方法被private修饰后不可被重写
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
7、接口和抽象类的区别?
抽象类:可以存在普通类型成员函数、成员变量可以是任何类型的,只能有一个子类继承
接口:只能存在public abstract 方法,只能使用 public static final 修饰变量,可以有多个实现
接口比抽象类要规范
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
8、Java 中 IO 流分为几种?
按功能来分:输入流(input)、输出流(output)。
按类型来分:字节流和字符流。
字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
9、BIO、NIO、AIO 有什么区别?
BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
10、Java 容器都有哪些?
Java 容器分为 Collection 和 Map 两大类,其下又有很多子类,如下所示:
Collection
List
ArrayList
LinkedList
Vector
Stack
Set
HashSet
LinkedHashSet
TreeSet
Map
HashMap
LinkedHashMapTreeMap
ConcurrentHashMap
Hashtable
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
11、List、Set、Map 之间的区别是什么?
List、Set、Map 的区别主要体现在两个方面:元素是否有序、是否允许元素重复。
三者之间的区别,如下表:
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
12、List和Set的区别?
List:有序,可以重复,允许null元素,可以使用迭代器Iterator取出元素,也可以for循环get(index)取出指定下标的元素
Set:无序,不可以重复,只允许一个null元素,只能使用Iterator迭代器遍历
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
13、HashCode与equals关系?
再你想插入一个数据近HashSet时,会计算生成此数据的hash码,再使用hashCode再hash表中找到对应的hash值后会通过equals进行比较是否相等,相等就不允许插入,不相等就允许插入,如果没有找到则会通过散列算法再找到另外一块位置放下
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
14、ArrayList与LinkedList区别?
ArrayList:基于动态数组结构,查询快,插入删除慢。如果是采用尾部插入法的话,效率还会比LinkedList效率高,因为LinkedList在插入数据时要创建一个node节点,在插入多个数据时性能会有所下降
LinkedList:基于链表结构,插入删除快,查询慢,用for循环遍历性能会很低(相当于从头开始一个个比较查询是否相等),使用Iterator迭代器遍历会更好
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
15、java类加载器有哪些?
1.bootstarpClassLoader:是extClassLoader父类加载器,专门加载%java_home%/lib的jar包以及class文件
2.extClassLoader,有一个parent属性,而这个parent就是,专门加载%java_home%/lib/ext的jar包以及class文件
3.appClassLoader,有一个parent属性,而这个parent就是etxClassLoader,专门加载classpath下的依赖jar包(系统类加载器,线程上下文加载器)
4.自定的ClassLoader必须继承appClassLoader类加载器
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
16、如何实现ioc容器?
1.定义配置文件的扫描包路径
2.定义各层的依赖注解
3.将带有注解的所有类或者是.class文件放入一个Set里存储
4.遍历Set,获取指定注解的类交给IOC容器(定义一个map,来存储这些对象)
5.遍历map,获取每一个类的实例,然后判断是否有其他类依赖于这个实例,再进行递归注入
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
17、什么是字节码?采用字节码的好处是什么?
java代码 → 编译器编译成.class文件 → jvm转换成可执行的java字节码 → jvm → 解析器解析成可执行二进制的机器码 → 交由机器执行
java将编译与解析分开了,这样子能够是性能上得到提升,像传统的语言是解析一句代码执行一句,java代码放在不同的平台(windows、linux。。。)运行时,不用进行重新编译
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
18、悲观锁和乐观锁
悲观锁:其代表的锁有synchronized、lock锁
其核心思想:只有线程占有了这个锁,才能访问其共享代码,如果有其它线程同时访问的话,除第一个线程外的线程都会进行几次获取锁的重试(减少阻塞),如果还是获取不到,那么就会挂起,也就是阻塞状态,阻塞的线程太频繁的唤醒阻塞也会影响性能
乐观锁:其代表的锁有AtomicInteger,使用acs来保证原子性
acs解释:
其核心思想:不用加锁,每次只有一个现成能成功修改共享变量,当线程获取锁失败的时候则会不断的重新尝试,也就没有了频繁切换上下文,性能相比悲观锁有所提升,但是吃cpu,并发线程数量不会超过cpu的核数
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
19、HashMap数据结构
jdk1.7:动态数组+链表
jdk1.8:动态数组+链表+红黑树
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
20、HashMap的红黑树树化
树化的意义:
树化后能抵御dos攻击,防止链表超时时影响性能,但是树化太多会影响程序性能,因为树节点比普通的节点占用的内存要大,如非必要,尽量不要使其树化
什么时候树化:
并且链表长度超过阈值8时,因为这个因子是0.75,所以8是最合适树化的时机,先尝试扩容来减少链表长度,当数组的长度大于等于64
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
21、HashMap红黑树的退化
什么时候退化:
当扩容并拆分红黑树时,链表长度小于等于6时退化成链表
当remove红黑树节点时,父节点,左子节点,左子子节点,右子节点有一个为null时就退化成链表结构
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
22、HashMap的索引(桶下标)如何计算
1.先用hashCode()方法计算一次hash值
2.再hash值 & hash值 >> 5 也就是hash()方法进行计算二次hash值
3.最后二次hash值 & (capacity(数组容量) -1) 等到索引 或者 hash值 % 数组容量也行,不过前者效率高
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
23、hashCode都有了,为啥还要提供hash方法?
因为hashCode的数组元素分布在数组不是均匀的,所以要进行二次hash,综合高位数据
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
24、数组容量为何是2的n次幂?
2的n次幂是为了让数组扩容时,能够通过位与运算来代替取模,如果元素最终运算的值==0,那么元素留在原来的索引位置,如果!=0那么在扩容时这些元素则会移动到原来位置索引+取模后的数字
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
25、HashMap的put方法流程
1. hashMap是懒惰创建数组,首次使用才会创建
2. 通过两次hash值得计算取得索引下标
3. 判断当前下标有无node占用,如果没有则创建node对象返回
4. 判断是否是红黑树,是的话走红黑树逻辑,是否是链表,是的话走链表逻辑,添加后是否超过树化的阈值,走红黑树的逻辑
5. 添加后返回前判断数组长度是否超出阈值需要扩容,如果超出,则先添加到旧数组再扩容
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
26、hashMap数组的加载(扩容)因子为何默认是0.75f?
1.一旦加载因子超过0.75,那么链表都会变得很长才会开始扩容,性能损耗大
2.一旦加载因子低于0.7么,那么当链表都还很短的情况数组就会开始扩容了,占用内存空间大
主要是为了在空间占用和性能方面取得了较好的权衡
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
27、HashMap多线程下会有啥问题?
1.7:因为是头插法所以在第一个线程put后,第二个线程再去循环put时,就会导致链表循环,死链的情况出现
1.7与1.8:数据错乱,丢失,当第一个线程还没put完成的时候,第二个线程就进来了,导致第二个线程的数据会覆盖第一个线程的数据,从而导致数据丢失
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
28、HashMap的key是否能为null,作为key的对象有什么要求?
可以为null,key对象不能够修改,必须实现hashCode()与equals(),因为当对象修改了属性之后就重新计算hash值,这样子在hashMap里面找不着了
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
29、HashMapString对象的hashCode()如何设计,为啥每次都是31
目标是达到较为均匀的散列效果,每个字符串的hashCode足够独特,31引入公式后可以被优化成效率散列效果平均最好的。质数也行,散列效果比31还好,只是质数引入公式后优化不了,性能会有所下降
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
30、双亲委派模型
当你要加载一个类或者一个资源的时候,不会在当前的类加载器加载而是去找类加载器的上层向上委托查找缓存,向上顶层后找不到在向下查找也就是各个类加载器的加载路径
好处:
1. 避免我们修改string类等的java核心类,提高了安全性
2. 避免了重复加载,因为jvm中区分不同类,不仅仅是根据类名,相同class文件被不同的classLoader(类加载器)加载,就是不同的两个类
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
31、java中异常的体系
顶级异常Thorwable分为以下两个子类
exception:可修复挽回的异常,抛出后不会暂停程序运行,这玩意又分了两个子类出来(RunTimeException【运行时异常,只会导致当前线程执行失败】,CheckedException【代码检查异常】)
error:无可挽回的异常,就比如说内存泄漏
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
32、GC如何判断对象可以被回收
可达性分析法:从GCRoots开始向下搜索,搜索过得路径为引用链,当一个对象没有被任何引用链相连接时,则此对象是可回收的。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
33、线程的生命周期,有哪几种状态
新建:创建新线程start
可运行:就绪准备运行了runable
阻塞:获取锁失败时,获取锁成功则切换到可运行
等待:调用wait()时,使用notify或者notifyAll时会被唤醒切换到可运行
限时等待:调用wait(long)或sleep(long)时,到时间后会被唤醒切换到可运行
终止:结束生命周期
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
34、ArrayList扩容机制
1.初始容量为0,无参构造
2.add方法第一次扩容为10,后面扩容的数量为扩容前容量 >>> 1,也就是1.5
3.addAll
没有元素时,如果实际元素大于10,则扩容实际元素,否则扩容10
有元素时,如果实际元素大于长度>>>1,则扩容实际元素,否则扩容长度 >>>1
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
35、fail-fast与fail-safe
fail-fast:(ArrayList)多线程遍历情况下不允许内容修改,否则会抛出并发异常
fail-safe:(CopyOnWriteArrayList)多线程遍历情况下允许内容修改,牺牲一些性能让整个遍历完成,因为源码是将读写分离了的,实时可以进行复制
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
36、线程池的核心参数有哪些?
1. 最大核心线程数目(corePoolSize)
2. 最大线程数目(maximumPoolSize)
3. 阻塞队列数目(workQueue)
4.救急线程存活时间(keepAliveTime)
5.救急线程存活时间单位(unit)
6. 线程工厂名称(threadFactory):为线程池取名字
7. 拒绝策略(handler):抛异常、直接丢弃线程、替换阻塞队列阻塞最久的线程、使调用者执行
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
37、wait()与sleep()区别?
wait():方法归属object会释放对象锁,其它线程可以来获取锁,可以通过notify或者notifyAll方法唤醒,只能配合锁一起使用
sleep():方法归属Thread,不会释放对象锁,其他线程不能获取锁,只能等待,没有限制只能配合锁一起使用
调用interrupt方法都可以被中途唤醒,都是暂时放弃cpu使用,进入阻塞状态
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
38、常见的设计模式(单例模式)
饿汉式:一开始就会加载,可以通过反射,反序列化,调用jdk的usafe方法产生多例
枚举饿汉式:有效防止多例的产生
懒汉式:只有用的时候才会加载,多线程时可能会导致数据丢失
双检锁懒汉式:为了线程安全
内部类懒汉式:为了线程安全
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
39、HashMap红黑树的退化
什么时候退化:
当扩容并拆分红黑树时,链表长度小于等于6时退化成链表
当remove红黑树节点时,父节点,左子节点,左子子节点,右子节点有一个为null时就退化成链表结构
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
40、在 Queue 中 poll()和 remove()有什么区别?
相同点:都是返回第一个元素,并在队列中删除返回的对象。
不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。
代码示例:Queue<String> queue = new LinkedList<String>();
queue. offer("string"); // add
System. out. println(queue. poll());
System. out. println(queue. remove());
System. out. println(queue. size());
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
41、哪些集合类是线程安全的?
Vector、Hashtable、Stack 都是线程安全的,而像 HashMap 则是非线程安全的,不过在 JDK 1.5 之后随着 Java. util. concurrent 并发包的出现,它们也有了自己对应的线程安全类,比如 HashMap 对应的线程安全类就是 ConcurrentHashMap。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
42、并行和并发有什么区别?
并行:多个处理器或多核处理器同时处理多个任务。
并发:多个任务在同一个 CPU 核上,按细分的时间片轮流(交替)执行,从逻辑上来看那些任务是同时执行。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
43、线程和进程的区别?
一个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也可以有多个线程来增加程序的执行速度。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
44、守护线程是什么?
守护线程是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。在 Java 中垃圾回收线程就是特殊的守护线程。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
45、 创建线程有哪几种方式?
创建线程有三种方式:
- 继承 Thread 重写 run 方法;
- 实现 Runnable 接口;
- 实现 Callable 接口。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
46、sleep() 和 wait() 有什么区别?
类的不同:sleep() 来自 Thread,wait() 来自 Object。
释放锁:sleep() 不释放锁;wait() 释放锁。
用法不同:sleep() 时间到会自动恢复;wait() 可以使用 notify()/notifyAll()直接唤醒
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
47、notify()和 notifyAll()有什么区别?
notifyAll()会唤醒所有的线程,notify()之后唤醒一个线程。notifyAll() 调用后,会将全部线程由等待池移到锁池,然后参与锁的竞争,竞争成功则继续执行,如果不成功则留在锁池等待锁被释放后再次参与竞争。而 notify()只会唤醒一个线程,具体唤醒哪一个线程由虚拟机控制。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
48、线程的 run() 和 start() 有什么区别?
start() 方法用于启动线程,run() 方法用于执行线程的运行时代码。run() 可以重复调用,而 start() 只能调用一次。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
49、创建线程池有哪几种方式?
线程池创建有七种方式,最核心的是最后一种:
①newSingleThreadExecutor():
它的特点在于工作线程数目被限制为 1,操作一个无界的工作队列,所以它保证了所有任务的都是被顺序执行,最多会有一个任务处于活动状态,并且不允许使用者改动线程池实例,因此可以避免其改变线程数目;
②newCachedThreadPool():它是一种用来处理大量短时间工作任务的线程池,具有几个鲜明特点:它会试图缓存线程并重用,当无缓存线程可用时,就会创建新的工作线程;如果线程闲置的时间超过 60 秒,则被终止并移出缓存;长时间闲置时,这种线程池,不会消耗什么资源。其内部使用 SynchronousQueue 作为工作队列;
③newFixedThreadPool(int nThreads):重用指定数目(nThreads)的线程,其背后使用的是无界的工作队列,任何时候最多有 nThreads 个工作线程是活动的。这意味着,如果任务数量超过了活动队列数目,将在工作队列中等待空闲线程出现;如果有工作线程退出,将会有新的工作线程被创建,以补足指定的数目 nThreads;
④newSingleThreadScheduledExecutor():创建单线程池,返回 ScheduledExecutorService,可以进行定时或周期性的工作调度;
⑤newScheduledThreadPool(int corePoolSize):和newSingleThreadScheduledExecutor()类似,创建的是个 ScheduledExecutorService,可以进行定时或周期性的工作调度,区别在于单一工作线程还是多个工作线程;
⑥newWorkStealingPool(int parallelism):这是一个经常被人忽略的线程池,Java 8 才加入这个创建方法,其内部会构建ForkJoinPool,利用Work-Stealing算法,并行地处理任务,不保证处理顺序;
⑦ThreadPoolExecutor():是最原始的线程池创建,上面1-3创建方式都是对ThreadPoolExecutor的封装。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
50、线程池都有哪些状态?
RUNNING:这是最正常的状态,接受新的任务,处理等待队列中的任务。
SHUTDOWN:不接受新的任务提交,但是会继续处理等待队列中的任务。
STOP:不接受新的任务提交,不再处理等待队列中的任务,中断正在执行任务的线程。
TIDYING:所有的任务都销毁了,workCount 为 0,线程池的状态在转换为 TIDYING 状态时,会执行钩子方法 terminated()。
TERMINATED:terminated()方法结束后,线程池的状态就会变成这个。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
51、线程池中 submit() 和 execute() 方法有什么区别?
execute():只能执行 Runnable 类型的任务。
submit():可以执行 Runnable 和 Callable 类型的任务。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
52、在 Java 程序中怎么保证多线程的运行安全?
方法一:使用安全类,比如 Java. util. concurrent 下的类。
方法二:使用自动锁 synchronized。
方法三:使用手动锁 Lock。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
53、什么是死锁?
当线程 A 持有独占锁a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
54、怎么防止死锁?
尽量使用 tryLock(long timeout, TimeUnit unit)的方法(ReentrantLock、ReentrantReadWriteLock),设置超时时间,超时可以退出防止死锁。
尽量使用 Java. util. concurrent 并发类代替自己手写锁。
尽量降低锁的使用粒度,尽量不要几个功能用同一把锁。
尽量减少同步的代码块。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
55、ThreadLocal 是什么?有哪些使用场景?
ThreadLocal 为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
ThreadLocal 的经典使用场景是数据库连接和 session 管理等。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
56、说一下 synchronized 底层实现原理?
synchronized 是由一对 monitorenter/monitorexit 指令实现的,monitor 对象是同步的基本实现单元。在 Java 6 之前,monitor 的实现完全是依靠操作系统内部的互斥锁,因为需要进行用户态到内核态的切换,所以同步操作是一个无差别的重量级操作,性能也很低。但在 Java 6 的时候,Java 虚拟机 对此进行了大刀阔斧地改进,提供了三种不同的 monitor 实现,也就是常说的三种不同的锁:偏向锁(Biased Locking)、轻量级锁和重量级锁,大大改进了其性能。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
57、synchronized 和 volatile 的区别是什么?
volatile 是变量修饰符;synchronized 是修饰类、方法、代码段。
volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变量的修改可见性和原子性。
volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
58、synchronized 和 Lock 有什么区别?
synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。
synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁;而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁。
通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
59、synchronized 和 ReentrantLock 区别是什么?
synchronized 早期的实现比较低效,对比 ReentrantLock,大多数场景性能都相差较大,但是在 Java 6 中对 synchronized 进行了非常多的改进。
主要区别如下:
ReentrantLock 使用起来比较灵活,但是必须有释放锁的配合动作;
ReentrantLock 必须手动获取与释放锁,而 synchronized 不需要手动释放和开启锁;
ReentrantLock 只适用于代码块锁,而 synchronized 可用于修饰方法、代码块等。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
60、说一下 atomic 的原理?
Atomic包中的类基本的特性就是在多线程环境下,当有多个线程同时对单个(包括基本类型及引用类型)变量进行操作时,具有排他性,即当多个线程同时对该变量的值进行更新时,仅有一个线程能成功,而未成功的线程可以向自旋锁一样,继续尝试,一直等到执行成功。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
61、什么是反射?
反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
62、什么是 Java 序列化?什么情况下需要序列化?
Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。
以下情况需要使用 Java 序列化:
- 想把的内存中的对象状态保存到一个文件中或者数据库中时候;
- 想用套接字在网络上传送对象的时候;
- 想通过RMI(远程方法调用)传输对象的时候。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
63、动态代理是什么?有哪些应用?
动态代理是运行时动态生成代理类。
动态代理的应用有 spring aop、hibernate 数据查询、测试框架的后端 mock、rpc,Java注解对象获取等。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
64、怎么实现动态代理?
JDK 原生动态代理和 cglib 动态代理。JDK 原生动态代理是基于接口实现的,而 cglib 是基于继承当前类的子类实现的。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
65、为什么要使用克隆?如何实现对象克隆?
克隆的对象可能包含一些已经修改过的属性,而 new 出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠克隆方法了。
- 实现 Cloneable 接口并重写 Object 类中的 clone() 方法。
- 实现 Serializable 接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
深拷贝和浅拷贝区别是什么?
- 浅克隆:当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。
- 深克隆:除了对象本身被复制外,对象所包含的所有成员变量也将复制。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
66、JSP 和 servlet 有什么区别?
JSP 是 servlet 技术的扩展,本质上就是 servlet 的简易方式。servlet 和 JSP 最主要的不同点在于,servlet 的应用逻辑是在 Java 文件中,并且完全从表示层中的 html 里分离开来,而 JSP 的情况是 Java 和 html 可以组合成一个扩展名为 JSP 的文件。JSP 侧重于视图,servlet 主要用于控制逻辑。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
67、session 和 cookie 有什么区别?
存储位置不同:session 存储在服务器端;cookie 存储在浏览器端。
安全性不同:cookie 安全性一般,在浏览器存储,可以被伪造和修改。
容量和个数限制:cookie 有容量限制,每个站点下的 cookie 也有个数限制。
存储的多样性:session 可以存储在 Redis 中、数据库中、应用程序中;而 cookie 只能存储在浏览器中。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
68、说一下 session 的工作原理?
session 的工作原理是客户端登录完成之后,服务器会创建对应的 session,session 创建完之后,会把 session 的 id 发送给客户端,客户端再存储到浏览器中。这样客户端每次访问服务器时,都会带着 sessionid,服务器拿到 sessionid 之后,在内存找到与之对应的 session 这样就可以正常工作了。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
69、如果客户端禁止 cookie 能实现 session 还能用吗?
可以用,session 只是依赖 cookie 存储 sessionid,如果 cookie 被禁用了,可以使用 url 中添加 sessionid 的方式保证 session 能正常使用。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
70、如何避免 SQL 注入?
使用预处理 PreparedStatement。
使用正则表达式过滤掉字符中的特殊字符。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
71、什么是 XSS 攻击,如何避免?
XSS 攻击:即跨站脚本攻击,它是 Web 程序中常见的漏洞。原理是攻击者往 Web 页面里插入恶意的脚本代码(css 代码、Javascript 代码等),当用户浏览该页面时,嵌入其中的脚本代码会被执行,从而达到恶意攻击用户的目的,如盗取用户 cookie、破坏页面结构、重定向到其他网站等。
预防 XSS 的核心是必须对输入的数据做过滤处理
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
72、什么是 CSRF 攻击,如何避免?
CSRF:Cross-Site Request Forgery(中文:跨站请求伪造),可以理解为攻击者盗用了你的身份,以你的名义发送恶意请求,比如:以你名义发送邮件、发消息、购买商品,虚拟货币转账等。
防御手段:
验证请求来源地址;
关键操作添加验证码;
在请求地址添加 token 并验证。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
73、throw 和 throws 的区别?
throw:是真实抛出一个异常。
throws:是声明可能会抛出一个异常。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
74、简述 tcp 和 udp的区别?
tcp 和 udp 是 OSI 模型中的运输层中的协议。tcp 提供可靠的通信传输,而 udp 则常被用于让广播和细节控制交给应用的通信传输。
两者的区别大致如下:
tcp 面向连接,udp 面向非连接即发送数据前不需要建立链接;
tcp 提供可靠的服务(数据传输),udp 无法保证;
tcp 面向字节流,udp 面向报文;
tcp 数据传输慢,udp 数据传输快;
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
75、tcp 为什么要三次握手,两次不行吗?为什么?
如果采用两次握手,那么只要服务器发出确认数据包就会建立连接,但由于客户端此时并未响应服务器端的请求,那此时服务器端就会一直在等待客户端,这样服务器端就白白浪费了一定的资源。若采用三次握手,服务器端没有收到来自客户端的再此确认,则就会知道客户端并没有要求建立请求,就不会浪费服务器的资源。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
76、说一下 tcp 粘包是怎么产生的?
tcp 粘包可能发生在发送端或者接收端,分别来看两端各种产生粘包的原因:
- 发送端粘包:发送端需要等缓冲区满才发送出去,造成粘包;
- 接收方粘包:接收方不及时接收缓冲区的包,造成多个包接收
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
77、OSI 的七层模型都有哪些?
物理层:利用传输介质为数据链路层提供物理连接,实现比特流的透明传输。
数据链路层:负责建立和管理节点间的链路。
网络层:通过路由选择算法,为报文或分组通过通信子网选择最适当的路径。
传输层:向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输。
会话层:向两个实体的表示层提供建立和使用连接的方法。
表示层:处理用户信息的表示问题,如编码、数据格式转换和加密解密等。
应用层:直接向用户提供服务,完成用户希望在网络上完成的各种工作。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
78、为什么要使用 spring?
spring 提供 ioc 技术,容器会帮你管理依赖的对象,从而不需要自己创建和管理依赖对象了,更轻松的实现了程序的解耦。
spring 提供了事务支持,使得事务操作变的更加方便。
spring 提供了面向切片编程,这样可以更方便的处理某一类的问题。
更方便的框架集成,spring 可以很方便的集成其他框架,比如 MyBatis、hibernate 等。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
79、解释一下什么是 aop?
aop 是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
简单来说就是统一处理某一“切面”(类)的问题的编程思想,比如统一处理日志、异常等。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
80、解释一下什么是 ioc?
ioc:Inversionof Control(中文:控制反转)是 spring 的核心,对于 spring 框架来说,就是由 spring 来负责控制对象的生命周期和对象间的关系。
简单来说,控制指的是当前对象对内部成员的控制权;控制反转指的是,这种控制权不由当前对象管理了,由其他(类,第三方容器)来管理
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
81、spring 常用的注入方式有哪些?
- setter 属性注入
- 构造方法注入
- 注解方式注入
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
82、spring 中的 bean 是线程安全的吗?
spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。
实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。
有状态就是有数据存储功能。
无状态就是不会保存数据。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
83、 说一下 spring 的事务隔离?
spring 有五大隔离级别,默认值为 ISOLATION_DEFAULT(使用数据库的设置),其他四个隔离级别和数据库的隔离级别一致:
ISOLATION_DEFAULT:用底层数据库的设置隔离级别,数据库设置的是什么我就用什么;
ISOLATIONREADUNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读);
ISOLATIONREADCOMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读),SQL server 的默认级别;
ISOLATIONREPEATABLEREAD:可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读),MySQL 的默认级别;
ISOLATION_SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
「脏读」 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。
「不可重复读」 :是指在一个事务内,多次读同一数据。
「幻读」 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
84、说一下 spring mvc 运行流程?
spring mvc 先将请求发送给 DispatcherServlet。
DispatcherServlet 查询一个或多个 HandlerMapping,找到处理请求的 Controller。
DispatcherServlet 再把请求提交到对应的 Controller。
Controller 进行业务逻辑处理后,会返回一个ModelAndView。
Dispathcher 查询一个或多个 ViewResolver 视图解析器,找到 ModelAndView 对象指定的视图对象。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
85、为什么要用 spring boot?
- 配置简单
- 独立运行
- 自动装配
- 无代码生成和 xml 配置
- 提供应用监控
- 易上手
- 提升开发效率
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
86、spring cloud 的核心组件有哪些?
Eureka:服务注册于发现。
Feign:基于动态代理机制,根据注解和选择的机器,拼接请求 url 地址,发起请求。
Ribbon:实现负载均衡,从一个服务的多台机器中选择一台。
Hystrix:提供线程池,不同的服务走不同的线程池,实现了不同服务调用的隔离,避免了服务雪崩的问题。
Zuul:网关管理,由 Zuul 网关转发请求给对应的服务。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
87、MyBatis 中 #{}和 ${}的区别是什么?
#{}是预编译处理,${}是字符替换。在使用 #{}时,MyBatis 会将 SQL 中的 #{}替换成“?”,配合 PreparedStatement 的 set 方法赋值,这样可以有效的防止 SQL 注入,保证程序的运行安全。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
88、MyBatis 有几种分页方式?
分页方式:逻辑分页和物理分页。
「逻辑分页:」 使用 MyBatis 自带的 RowBounds 进行分页,它是一次性查询很多数据,然后在数据中再进行检索。
「物理分页:」 自己手写 SQL 分页或使用分页插件 PageHelper,去数据库查询指定条数的分页数据的形式。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
89、RowBounds 是一次性查询全部结果吗?为什么?
RowBounds 表面是在“所有”数据中检索数据,其实并非是一次性查询出所有数据,因为 MyBatis 是对 jdbc 的封装,在 jdbc 驱动中有一个 Fetch Size 的配置,它规定了每次最多从数据库查询多少条数据,假如你要查询更多数据,它会在你执行 next()的时候,去查询更多的数据。就好比你去自动取款机取 10000 元,但取款机每次最多能取 2500 元,所以你要取 4 次才能把钱取完。只是对于 jdbc 来说,当你调用 next()的时候会自动帮你完成查询工作。这样做的好处可以有效的防止内存溢出。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
90、说一下 MyBatis 的一级缓存和二级缓存?
一级缓存:基于 PerpetualCache 的 HashMap 本地缓存,它的声明周期是和 SQLSession 一致的,有多个 SQLSession 或者分布式的环境中数据库操作,可能会出现脏数据。当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认一级缓存是开启的。
二级缓存:也是基于 PerpetualCache 的 HashMap 本地缓存,不同在于其存储作用域为 Mapper 级别的,如果多个SQLSession之间需要共享缓存,则需要使用到二级缓存,并且二级缓存可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态)。
开启二级缓存数据查询流程:二级缓存 -> 一级缓存 -> 数据库。缓存更新机制:当某一个作用域(一级缓存 Session/二级缓存 Mapper)进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
91、MyBatis 是否支持延迟加载?延迟加载的原理是什么?
MyBatis 支持延迟加载,设置 lazyLoadingEnabled=true 即可。
延迟加载的原理的是调用的时候触发加载,而不是在初始化的时候就加载信息。比如调用 a. getB(). getName(),这个时候发现 a. getB() 的值为 null,此时会单独触发事先保存好的关联 B 对象的 SQL,先查询出来 B,然后再调用 a. setB(b),而这时候再调用 a. getB(). getName() 就有值了,这就是延迟加载的基本原理。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
92、RabbitMQ 的使用场景有哪些?
抢购活动,削峰填谷,防止系统崩塌。
延迟信息处理,比如 10 分钟之后给下单未付款的用户发送邮件提醒。
解耦系统,对于新增的功能可以单独写模块扩展,比如用户确认评价之后,新增了给用户返积分的功能,这个时候不用在业务代码里添加新增积分的功能,只需要把新增积分的接口订阅确认评价的消息队列即可,后面再添加任何功能只需要订阅对应的消息队列即可。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
93、RabbitMQ 有哪些重要的角色?
RabbitMQ中重要的角色有:生产者、消费者和代理:
- 生产者:消息的创建者,负责创建和推送数据到消息服务器;
- 消费者:消息的接收方,用于处理数据和确认消息;
- 代理:就是 RabbitMQ 本身,用于扮演“快递”的角色,本身不生产消息,只是扮演“快递”的角色
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
94、RabbitMQ 有哪些重要的组件?
ConnectionFactory(连接管理器):应用程序与Rabbit之间建立连接的管理器,程序代码中使用。
Channel(信道):消息推送使用的通道。
Exchange(交换器):用于接受、分配消息。
Queue(队列):用于存储生产者的消息。
RoutingKey(路由键):用于把生成者的数据分配到交换器上。
BindingKey(绑定键):用于把交换器的消息绑定到队列上。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
95、RabbitMQ 怎么保证消息的稳定性?
提供了事务的功能。
通过将 channel 设置为 confirm(确认)模式
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
96、 RabbitMQ 怎么避免消息丢失?
把消息持久化磁盘,保证服务器重启消息不丢失。
每个集群中至少有一个物理磁盘,保证消息落入磁盘
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
97、RabbitMQ 怎么实现延迟消息队列?
延迟队列的实现有两种方式:
- 通过消息过期后进入死信交换器,再由交换器转发到延迟消费队列,实现延迟功能;
- 使用 RabbitMQ-delayed-message-exchange 插件实现延迟功能。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
98、说一下 JVM 的主要组成部分?及其作用?
类加载器(ClassLoader)
运行时数据区(Runtime Data Area)
执行引擎(Execution Engine)
本地库接口(Native Interface)
「组件的作用:」 首先通过类加载器(ClassLoader)会把 Java 代码转换成字节码,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行,而这个过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
99、说一下堆栈的区别?
- 功能方面:堆是用来存放对象的,栈是用来执行程序的。
- 共享性:堆是线程共享的,栈是线程私有的。
- 空间大小:堆大小远远大于栈。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
100、说一下类装载的执行过程?
类装载分为以下 5 个步骤:
加载:根据查找路径找到相应的 class 文件然后导入;
检查:检查加载的 class 文件的正确性;
准备:给类中的静态变量分配内存空间;
解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;
初始化:对静态变量和静态代码块执行初始化工作。
有自己的见解或者有补充的小伙伴请在评论区带上题目编号进行回复哦,我会第一时间进行修改,谢谢大家!
101、
102、
103、
104、
。。。。。未完待续
。。。。。未完待续
下边为我的公众号,有兴趣的小伙伴可以一起讨论
最后附上
一寸光阴一寸金,寸金难买寸光阴。请珍惜现在美好的青春,咱们一起努力奋斗,创造美好未来
拜托拜托!!!拜托拜托!!!拜托拜托!!!
BIT PLANET
![](https://i-blog.csdnimg.cn/blog_migrate/eac9d40b8f93f30b079f5382ef6808f2.jpeg)