当前位置: 首页 > news >正文

JAVA高频面试题

HashMap的底层数据结构?

jdk8以前:数组+链表

Jdk8以后:数组加链表加红黑树


为什么要引入红黑树?

链表长度大于8之后,会从链表变成红黑树,这样做的目的时因为链表的查询复杂度为O(1)而红黑树在数据量大的时候,他的查询效率要比链表的高。


扩容机制是什么?为什么他的数组长度永远都是2的幂次?

1.是根据扩容因子来的默认是0.75,比如长度为16,那么到了16*0.75=12时,就进行扩容,扩容的长度为16*2=32。

2.因为底层的Hash算法,2的幂次的长度有利于他更均匀的分配数据


为什么在JDK7到JDK8要把头插改成尾插?为什么他解决冲突的方式是链表加红黑树?

1.在并发的时候不安全,两个线程同时进行扩容操作,会把链表变成环形链表,出现死循环的结果

2,链表加红黑树并没有“减少”冲突的发生次数,而是“优化”了冲突发生后的处理效率,极大地缓解了冲突带来的性能瓶颈。链表的时间复杂度为O(n),红黑树的时间复杂度O(logN),时间复杂度优化了,处理冲突和判断是否有冲突的处理效率高了。


ArrayList和LinkedList有什么区别?

前者是底层数据结构是数组,后者是链表,链表适合删除或者新增头节点和尾节点,前者适合查询


ConcurrentHashMap是怎么实现的?ConcurrentHashMap在JDK7到JDK8做了什么升级?

他是线程安全的HashMap,

JDK7

主要是靠那个分段锁实现并发安全,默认有16个segment数组,每个都有一把锁,一共16个小锁,各个线程操作不同的段,互不打扰。可以简单的认为每个segment存放的就是一个单独的HashMap。

JDK8

由于并发度是由他的数组大小决定的,那么数组一旦初始化,后期的扩容只能一段一段的扩,性能提升有限。JDK8直接摒弃了segment,用Node节点代替,每个桶上一把锁,锁的粒度更小了,而且插入时,优先用CAS无锁状态插入,冲突了再加Synchronizd。

而且和HashMap一样,1.7是数组加链表,1.8是数组加链表加红黑树。


什么是乐观锁和悲观锁,CAS是怎么实现的?

这是一种思想,乐观的认为不会发生并发冲突,所以他的核心观念就是不加锁,

悲观锁就是悲观的认为并发冲突一定会发生,所以他把读和写都加上了锁,安全是安全,不过性能太低了,干啥都加锁。

CAS就是基于乐观锁的思想实现的一种机制,比较并交换,先说比较,线程用自己的old value和共享资源的new value进行比较,比较通过了,那就交换这两个值,拿到共享资源,没有拿到共享资源的线程就一直自旋,等待共享资源的释放,顺便提一下,比较并交换是两步操作,他的原子性是通过硬件锁,锁住总线的方式来保证的

ABA问题:

这个问题就是线程1想要访问共享变量A,但是在这之前,线程2他把共享变量改成了B,这个时候线程2把他又改回了A,共享变量:A->B->A

这个时候虽然共享变量的值改回去了。但是这个变化可能意味着某些依赖条件已经改变(例如,在链表操作中,节点可能已经被移出链表后又重新加入),导致 线程1 的 CAS 成功可能是不正确或危险的。

解决办法:

就是给他加一个版本号,让他每次修改的时候。版本号就会变化(默认是递增),这样就能够保证他的一个正确性了。


Synchronized和ReenTrantLock有什么区别?

主要有以下三点区别:

1.ReentrantLock他是基于AQS实现的,AQS底层有tryAquire()方法,对应到ReentranLock这里就是TryLock,尝试获取锁,获取到了,我就执行,获取不到我就能干别的事去了。这是Syntranized没有的

2.公平锁和非公平锁机制:Synchronizd是非公平的锁,reentranLock锁是既可以公平又可以非公平,reentranlock里有两个子类,fireSync和NonfireSync,二者都重写了tryquire方法,前者是用的等待队列,先进先出,保证了公平性,后者实现了插队的功能,保证了非公平性。

3.Synchronizd有锁池和等待池,锁池存放的是获取锁失败的线程,等待池他存放的是通信时主动放弃锁的线程,reentrantLock:获取锁失败的线程放在等待队列中,获取锁成功但是还要等资源响应的线程放在Condtion类中。


原子类是如何实现的?

volatile + CAS + (自旋/适应性策略)

volatile:保证可见性

CAS:解决了原子性问题,他底层是加了硬件锁嘛。

自旋/适应性策略:解决了获取锁失败后的处理策略

Volatile的关键字有什么作用?

他的作用是保证线程之间的可见性,他的底层实现,其实是依靠cpu的缓存一致性协议来实现的


什么是JMM?什么是指令重排序?什么是happens before原则?

1.以"一次编译,到处运行"为宗旨,为了屏蔽这个不同的操作系统的内存模型的影响,自己创建了一个内存模型:JMM

内存模型如图,线程要获取数据,首先要先把共享数据读到主内存在进行计算,计算完之后再把数据刷回到主内存

工作内存和共享内存之间的交互,JMM设计了八种原子操作

简单来说就是对主存加锁,拿到变量去工作内存,然后把变量更新之后放回到主存,然后解锁。

指令重排序:

JMM数据交互的操作执行的时机,具体怎么实现,就要靠内存屏障去保障内存操作的顺序性和可见性

happens before规则

传递性:a->b b->c a->c

happens before b,也就是说单线程内,前面的操作对于后面的操作是可见的


Synchronized锁升级的流程?

为什么要锁升级?

不同的时间点锁竞争和并发量是不同的,高并发的时间点其实不多,每次线程获取锁失败,要被阻塞时,底层的操作系统都要从用户态转变为内核态,开销会很大。

无锁:这个时候,适用于深夜基本上没人买东西的时候,并发量非常小,没有加锁的必要

偏向锁:当有一个线程来抢锁,那此时就升级为偏向锁

轻量级锁:当第二个线程来抢锁我就升级为轻量级锁,没有拿到资源的线程就自旋,不用阻塞,这样就避免了性能开销。而且此时线程自旋的时间不会特别长,CPU的浪费不会特别多。

重量级锁:当线程多了,锁竞争激烈的时候,你就不能只让他自旋了,不然自旋时间特别久的话,他是非常浪费CPU资源的(拿着资源不干事)

锁监视器:

锁监视器是一个对象。里面有四个主要的字段

持有锁的线程:记录当前获取锁的线程

等待池:调用wait()方法的线程,也就是主动放弃锁的线程

锁池:获取锁失败的线程

记录锁的重入次数:计数器,记录重入次数

都是阻塞的线程为什么要分别放在两个地方呢?

这是因为等待池里的线程是调用wait()方法主动放弃锁,是为了等待别的资源齐全了,再执行自己的方法。锁池是获取锁失败的线程,他想的是立马抢到锁然后执行。


Synchronized是不是可重入锁,可重入锁是为了保证什么?

1.Synchronized是可重入锁

2.可重入锁为了保证防止自我死锁的场景,普通锁的场景:比如线程A拿到了一把锁(锁了很多方法,是个大代码块),但是线程A还想访问里面的方法,那就还需要获取同一把锁,但是只能获取一次锁,那这个时候是既不能调用里面的方法,又不能退出来(因为锁还没有释放),所以这个时候就死锁了。

所以要有可重入锁:

拿到锁进来大代码块里了,然后计数器+1,然后你又要拿大代码块里面的方法的锁,那这个时候,计数器+1,等到你把两个方法都执行完了,那就计数器-1再-1,此时计数器=0,所以锁释放。


AQS队列是怎么实现的,他是怎么实现一个公平锁的?

他是把一个个的线程看成一个个节点,然后把它们组成一个双向链表,基于双向链表的一个等待队列,双向链表是为了保证过期的线程能够更好的及时被移除,执行发现过期的节点,直接用prev方法定位到上一个节点,然后在直接next下一个有效节点就OK了。独享模式和共享模式,前者是一次唤醒一个线程,后者是需要多少个线程就唤醒多少个。

等待队列的特性就是先进先出嘛,那自然就能够保证线程的公平性


线程池的核心参数是什么?他提交任务的流程是什么,他的线程池的核心参数又要怎么计算?

线程的创建和销毁开销非常的大,那为什么大呢?

注意:java21创建了虚拟线程,那就不用转换操作系统状态就能完成线程的创建与销毁。

因为java他是一对一的线程模型,就是java创建一个线程,操作系统就要从用户态转换到内核态去进行操作,销毁线程也是一样。这种状态的改变时非常的消耗性能的。

那我们能不能不要频繁的去创建和销毁线程?

能,找个容器给他存起来线程池里面有线程(正式牛马),有任务过来了,我的线程就去处理任务。当任务越来越多的时候,如果忙不过来,那就用个任务队列(桌上没处理的文件)把他们存起来。(没完成的工作先放着),如果还忙不过来,就找了几个临时工:创建几个临时线程(实习生),那如果任务执行完了,大伙没活干了,临时线程就要被销毁,所以就要设置一个临时线程的最大空闲时间(实习期)

那如果要是任务队列满了,又有新的任务来了,线程和临时线程都在忙,根本有心无力这时候该怎么办呢?

那就涉及到拒绝策略了

那问题又来了,这个时候创建线程是创建普通线程还是守护线程呢?创建线程的时候又该怎么去给线程命名,所以就要搞一个线程工厂,让他去负责统一创建线程,根据业务对线程命名,这样就好排查问题:业务出了问题就能定位到具体的线程池和线程,线程出了问题也能定位到业务,所以不同的业务要用不同的线程池。

所以线程池的七大参数:

1.核心线程数(正式牛马)、最大线程数(正式+实习牛马),线程工厂(根据规则创建线程),拒绝策略,临时线程的空闲时间(实习期)、时间单位、阻塞队列(堆积任务)

接口和抽象类有什么区别?

接口中的方法,类里实现起来要重写他的所有方法

抽象类是一个类,他是为了开发规范发明的一个类

什么是单例模式?能给我写一个双重锁的检查吗?

单例模式就是确保一个类 只能创建一个对象 的设计模式

public class Singleton {// volatile 关键字确保多线程环境下的可见性和禁止指令重排序private static volatile Singleton instance;// 私有构造函数:禁止外部 new 创建对象private Singleton() {System.out.println("Singleton created");}// 全局访问点public static Singleton getInstance() {// 第一次检查:如果已存在实例直接返回(避免不必要的同步)if (instance == null) {// 同步代码块:保证只有一个线程进入创建synchronized (Singleton.class) {// 第二次检查:防止阻塞线程恢复后重复创建if (instance == null) {instance = new Singleton();}}}return instance;}
}

Mysql的事务隔离级别?什么是ACID?

ACID:原子性,隔离性,持久性,一致性

读未提交(啥都解决不了),读已提交(解决脏读),不可重复读(解决可重复读),串行化(都可以解决)


在MVCC下可重复读是怎么实现的,他还有幻读的可能性吗?

快照读:事务开始时就拍了张照片,然后你的事务结束前都是参考这张所谓的照片去读取数据的。

当前读:这时候要修改某个数据,当然只能拿最新的数据,这就是当前读,读当前最新的数据

1.MVCC的可重复读就是他的快照读实现的,重复的读一张照片,怎么读都还是那些数据

2.不能完全解决幻读问题

事务1是单纯的查询,是快照读,这时候比如读出来3条数据,事务2插入了一条数据,并且提交了事务,然后,事务1要修改事务了,那必须是切换为当前读,所以这个时候读到了最新的数据,总数记录变成了4条,所以此时幻读了。


什么是间隙锁?什么是临间锁?

间隙锁:防止插入的范围锁,在某个范围不能插入,锁的范围是(10,15)全开的区间,锁住的区间不能新增

临键锁:这个也是范围锁,但是是(10,15]左开右闭区间,锁住的区间不能新增删除修改

二者的区别就是;锁的范围不一样,然后能避免幻读。


什么是索引的回表查询,怎么避免这个问题?

你一开始访问的是二级索引,他的叶子节点上挂着Id,然后你拿着这个Id再去找对应Id的数据,

创建索引的时候少创建二级索引。避免索引失效,比如最左前缀法则等等,然后保证他能够走主键索引


mysql有哪些常见的索引?索引在哪些情况下会失效?

常见的索引:主键索引,二级索引

违反最左前缀法则,在索引上实现运算


有用过explain这个关键字嘛?

这个关键字用于查询sql语句的执行情况,放在sql语句的前面,然后他查出来的结果有一些参数:执行耗时,是否全表查询,走的什么索引等等


Inndb下Mysql的索引数据结构是什么?

他是优化后的B+树索引,底部之间的节点形成一个双向链表,用这个数据结构的好处是他的数据全都在叶子节点上,方便我们查询。


mysql的三大日志?

undoLog:

bingdoLog:

redolog:适用于事务的回滚


Redis的数据类型,  底层实现原理,  使用场景

String:                    动态字符串            缓存

list                            双向链表             消息队列,消息列表     

set                             集合                      朋友圈点赞

zset                         跳表+hash表               排行榜

Hash                      Mapmap(value也是键值对)        用户信息,商品信息  


缓存击穿/穿透/雪崩

缓存穿透:

大量前端请求到一个不存在的key,缓存中没有这个key,全部去查数据库,导致数据库的压力巨大。

解决办法:

1.缓存空值,对value为空的key也存在缓存(对内存压力很大)

2.布隆过滤器

缓存击穿:热key在某个时间过期了,然后大量请求过来,压力打到数据库。

解决办法:1.互斥锁(线程1发现key过期了,加一把锁,然后重建数据库)

2.逻辑过期

雪崩:就是某个redis服务崩了,或者大量的key同时失效,导致这个大量的请求打到数据库,然后导致数据库压力巨大

解决办法:

1.redis的集群模式

2.给key的过期时间设置随机值


redis和数据库的一致性问题?

1.先删除缓存和先删除数据库都会有脏数据的产生。

2.使用延迟双删,修改完数据库之后隔一段时间再删一次缓存,不过具体延迟多久也不清楚,所以也会有脏数据。

3.使用MQ的消息监听,把二者联系起来,依靠MQ的可靠性

4.用cancel作为中间件,也是监听的功能


redis为什么快,redis的IO多路复用模型?

redis的IO多路复用模型?

//TODO

1.redis是内存,是硬件的特性导致的他快

2.用一个线程去管理这些个socket,这些socket可读可写时会第一时间通知这个线程,当socket准备就绪了的时候,他会在通知用户进程的同时,把socket推送给用户空间,避免了他们遍历socket判断是否就绪浪费很多时间


能用redis去实现一套登录的机制嘛

redis的登录,登录重要的是token的存储和验证,以及之后的用户注销(删除token记录)

存储token:

redis存储token,设置过期时间,用的是hash结构存储的这个token (key:User_Token,value:token)防止token泄漏还可以:用jwt签名算法加密

验证token:

找一下redis中是否含有token,并且有没有过期,过期了就自动续签,更新过期时间

删除用户:redis删token

在线用户数量的统计:统计key的数量


redis的主从同步,redis的持久化机制

redis的主从同步:

这是redis集群的问题,为了防止reids的压力太大导致宕机,从而导致缓存雪崩,设计了一套这个redis的主从模式,用一个keepalive的插件去时刻监听主节点,主节点跪了,立马从节点顶上,那这么多的从节点,我怎么知道该选哪个?这个时候就看三个方面,第一个是内存大的redis先顶上,因为内存大,能存更多的数据。第二个就是看复制偏移量,主从节点之间是有联系的,从节点会复制主节点的数据,复制的越多复制偏移量就越大,那数据最接近于主节点的从节点就是最适合当主节点的。第三个就是按照序号排了。


redis中的大Key和热Key你该怎么去优化?

大Key:

1.分片存储,把大key拆分成很多的小key

2.调整参数,让系统优先用一些小型的集合去装我们的key,如果key能压缩,比如文本,那就可以先压缩一下

3.定期删除:把redis里面的key定期删除一下,释放内存

热Key:

读多写少的场景:

1.把他多分到几个从节点里头,支持读操作

2.还可以放在本地缓存里头

3.设置VIP的key,让他单独的放在一个节点里,独享服务

4.第一个线程进来,拿到的结果,回去共用

5.设置永不过期,避免缓存击穿,

6.熔断降级: 如果发现Redis快扛不住了(访问量爆炸),直接返回一个默认值(比如“服务繁忙”或者一个缓存的老数据),保护Redis别被冲垮。


有没有JVM的调优,JVM的垃圾回收算法,JVM的内存空间?

什么是垃圾

如果应该对象已经没有任何应该地方引用他,他就是垃圾

怎么确认是垃圾
引用计数法

给对象添加一个引用计数器,每当有一个地方引用它时,计数器加一。反之每当一个引用失效时,计数器减一。当计数器为0时,则表示对象不被引用。

可达分析
设立若干根对象(GC Root),每个对象都是一个子节点,当一个对象找不到根时,就认为该对象不可达。

触发条件

Minor GC触发机制
当年轻代满时就会触发Minor GC,这里的年轻代指的是Eden代满,Survivor满不会引发GC。

FULL GC触发机制
老年代空间不足方法区空间不足通过Minor GC后进入老年代的平均大小大于老年代的可用内存。由Eden区、From Survivor区向To Survivor区复制时,对象大小大于To Space可用内存,则把对象转存到老年代,且老年代的可用内存小于该对象大小System.gc()方法的调用,系统建议执行Full GC,但是不必然执行。

JVM的垃圾回收算法

标记清除法:标记到的对象就会被清除,然后再这样会产大量的内存碎片。

标记压缩法:在标记清除法上面做了优化,清除完的空间会被压缩。


逃逸分析?

new 一个对象,一般是会放在堆区,但这也不是绝对的,比如new 的一个对象只在他的方法里面运行,那就把它放到本地方法栈,这样做的好处就是:方法栈里面的对象用完就直接清理掉了,大大减轻了GC的压力


如何避免out of memory这个错误?(OOM)

1.避免直接读取大文件到内存,而是分批次,流式处理,分块读取

2.ThreadLocal变量使用完之后没有调用remove()方法去删除,线程池复用线程时,ThreadLocal数据残留,导致内存泄漏。久而久之就会内存溢出,解决办法就是及时的删除ThreadLocal,用finally{ remove() }

3.创建大量线程,超过了内存就会容易OOM,我们可以用线程池对线程进行管理

内存泄漏

内存溢出:


你的项目中有没有内存泄漏的问题?

  1. 长生命周期对象持有短生命周期对象引用
    比如在一个单例的工具类中,缓存了大量临时生成的业务对象(如用户请求数据),但没有及时清理。这些对象本应随请求结束被回收,却因被单例持有导致长期驻留内存,最终 OOM。
    解决:改用弱引用(WeakReference)存储缓存,或定时清理过期数据,结合缓存淘汰策略(如 LRU)。

  2. 资源未正确释放
    例如使用 ThreadLocal 存储线程上下文信息后,在 Web 环境中未调用 remove (),导致 Tomcat 线程池的核心线程长期持有对象引用。此外,IO 流、数据库连接未在 finally 中关闭也可能引发类似问题。
    解决:通过 AOP 或拦截器统一处理 ThreadLocal 的清理,使用 try-with-resources 确保资源自动释放,并结合 JVM 监控工具(如 VisualVM)定期排查。


Springboot涉及了哪些设计模式?

单例模式:每个类都有一个实例对象。在IOC容器中,对于单例作用域的Bean,容器只创建一个实例对象

单例模式的两个模式:饿汉模式,懒汉模式
饿汉模式:在IOC容器启动时就会创建Bean,Springboot的设计模式更倾向于饿汉模式,但只要我们在Bean类上加一个@Lazy注解,这个Bean就会在第一次访问时才会创建

懒汉模式:调用他的访问方法才会创建Bean。

单例Bean的好处:

建造者模式:

一般时Build为后缀,有build类对类的属性值修改就会方便很多

工厂模式:

工厂模式:就是你要完成一个支付的接口,你就创建三个支付类,支付类调用相应的支付接口,微信调用微信支付。

策略模式:是创建三个支付的方法,要支付的时候直接调用支付方法

Spring中a依赖b,b依赖a,spring是怎么解决的?

这是设计问题,合理的解决方案应该是:创建一个C,并且将a,b作为C类的成员变量,这样的话就是C依赖于a和b,这样能很好的避免循环依赖的问题。

更深入的讲:

容器去构建一个A时,会发现还需要一个B,构建B会发现还需要一个A,这样就会死循环。

具体方案:使用二级缓存:容器会去检测是否存在循环依赖,如果存在,首先构建A的过程,会先实例化A,并且放入二级缓存(A的状态:实例化未属性填充未初始化)填充A的属性的时候,会发现需要一个B属性,那么就去创建B,发现又需要一个A,此时我们从二级缓存中,去拿到一个半初始化状态的A(早期暴露的Bean),把他赋值给B对象,那么B创建好之后,将B的引用赋值给A,再将A从二级缓存中拉到一级缓存,那就完成了。


AOP是怎么实现的

切面编程,把一些共性的方法抽取出来,做成一个Aop的类,类里面就有共性的逻辑

然后有方法需要用这个共性的方法就在开头加一个注解

2.3 通知
通知定义了切面的具体行为,也就是在何时、何地、以何种方式对目标方法进行增强。根据增强发生的时机,通知分为:

前置通知(Before Advice):在方法调用前执行。
后置通知(After Advice):在方法调用后执行。
返回通知(After Returning Advice):在方法成功返回后执行。
异常通知(After Throwing Advice):在方法抛出异常后执行。
环绕通知(Around Advice):在方法执行的前后都执行,可以完全控制方法的执行过程。


除了JDK的动态代理,你还了解其他的代理模式吗

静态代理:代理角色对被代理角色某个方法执行前或者后进行功能增强

也就是中介对房东的收租方法增强了,中介帮房东讲价了


Spring的AOP是运行时代理还是编译时代理?

AOP是运行时代理,他避免了编译阶段对目标类字节码的直接修改


事务注解什么时候会失效?

@Transactional注解失效的重点场景可以归纳为以下几类:

  1. 方法访问权限问题:注解仅对public方法生效,非 public 方法(如 private)的事务会失效。

  2. 自调用场景:同一类中方法互相调用时,被调用方法的事务会失效,因为未经过 Spring 代理对象。

  3. 异常处理不当

    • 捕获异常后未重新抛出
    • 抛出的异常不在rollbackFor指定范围内(默认只处理 RuntimeException 和 Error)
  4. 类未被 Spring 管理:未加@Service等注解的类,事务注解不生效。

  5. 配置问题

    • 传播行为配置错误(如 NOT_SUPPORTED)
    • 数据库引擎不支持事务(如 MyISAM)
    • readOnly=true 时执行写操作

这些场景的核心原因是违背了 Spring 事务基于 AOP 代理的实现机制,导致事务增强逻辑无法正常触发。


redis的各种场景下的作用

String结构:

计数器

Redis的String的原子性的自增操作,可以去做一个计数器,记录某个网页的访问量,Key:网页视频Id,value:访问次数。

计数器限流:

针对IP或者接口做一个限流,路径为Key,访问次数为value。到了一定的阈值时,比如每分钟超过120次时,我们就拒绝请求。存在隐患:第一分钟和第二分钟的一个交界处,他会允许两倍的流量,比如说极端情况60秒来了120个请求,61秒来了120个请求,两秒内(几乎同一时间来了240个请求)这种情况是redis限流器解决不了的

Hash结构

购物车:id为key,商品id为field,然后商品数据时Value

不可靠的配置中心

List结构:

双端队列(有序可重复)

先进先出,后进先出,都可以

实现一个简单的消息队列,生产者创建任务放到消息队列里,消费者去拿。要保证消息队列的幂等性,那就每个消息都设置一个唯一id,消费者去保存这些处理过的消息id,避免重复消费。

Set

点赞,set集合可以交集并集,所以共同好友,共同爱好都可以

Zset:

排行榜:主要是依赖他的底层是有序的特性

滑动窗口的限流:用户IP为key,时间戳为socre

MyBatis的一级二级缓存

一级缓存:基于PerpetualCache的HashMap本地缓存,其存储的作用域为Session,Session级别的缓存,当Session进行flush或者close之后,该Session中的所有Cache就将被清空,一级缓存默认是打开的。

二级缓存:基于namespace和mapper的作用域起作用的,默认也是PerpetualCache的HashMap本地缓存,需要单独开启。

二级缓存什么时候会被清理?

当作用域下发生了增删改的时候,它里面的select会全部删除。

MyBatis的执行流程:

1.读取Mybatis的配置文件()

2.构建会话工厂()

3.会话工厂设置session对象(包含了所有的sql语句)

4.操作数据库接口,executor执行器,同时负责缓存的维护

5.输入参数映射

6.输出结果映射

MyBatis是否支持延迟加载?

开启全局延时加载:

延时加载和立即加载的区别:

比如Dish表里边有口味表,我要查菜品名字的时候

延时加载:我会只查询菜品表,口味表等需要查到的时候再查

立即加载:我会把两个表的数据都查出来

底层原理:

1.使用了CGLIB创建目标对象的代理对象

2.当调用目标方法时,进入拦截器的invoke方法

进程和线程和协程的区别?

线程基础

线程池的种类有哪些?

1.创建使用固定线程数的线程池

特点:核心线程数和最大线程数一样,没有救急线程

阻塞队列是LinkedBlockingQueue,最大容量为Integer.MAX_VALUE

适用场景:适合任务量已知的时候,相对耗时的任务

2.单线程化的线程池

特点:核心线程数和最大线程数都是1

阻塞队列是LinkedBlockingQueue,最大容量为Integer.MAX_VALUE

适用场景:按照顺序执行任务的线程

3.可缓存线程池

核心线程数是0

最大线程数:Integer.MAX_VALUE

阻塞队列为SynchronousQueue:不存储元素的阻塞队列,每个插入操作都必须等待一个移出操作。

适合任务数比较密集,但每个任务执行时间较短的情况

http://www.dtcms.com/a/557499.html

相关文章:

  • 如何制作一个自己的网站?安全教育平台登录入口网址
  • 软考 系统架构设计师系列知识点之杂项集萃(184)
  • Redis性能提升秘籍:大Key与热点Key优化实战
  • 大专物流管理专业职业发展指南
  • 徐州网站制作机构做猎头需要用到的网站
  • 石家庄做网站制作公司做公司点评的网站
  • Git指令集
  • 基于边缘信息提取的遥感图像开放集飞机检测方法
  • 前端基础知识---Promise
  • Java 基础——函数式编程
  • webkitx(Android WebView 最佳实践库)
  • 调查网站做调查不容易过横栏建设网站
  • 勐海县住房和城乡建设局网站南昌做网站费用
  • 感知上下文并可解释地预测合成致死药物靶点的大语言模型研究
  • AI研究-117 特斯拉 FSD 视觉解析:多摄像头 - 3D占用网络 - 车机渲染,盲区与低速复杂路况安全指南
  • 二级域名可以做网站吗免费个人博客网站模板下载
  • 复原大唐3d项目测试版
  • 2024年MySQL 下载、安装及启动停止教程(非常
  • 兰州百度网站建设百度网站关键词优化在哪里做
  • Redis——Windows安装
  • 微信网站开发视频教程免费的黄金软件
  • 【高级机器学习】0. Machine Learning 介绍
  • 昆明城乡和住房建设局网站网站做5级分销合法吗
  • .NETCore、.NET 7 和 RabbitMQ 的发布-订阅模式
  • Crashpad 在windows下编译和使用指南
  • 基于SpringBoot+Vue的农产品销售系统【协同过滤推荐算法+可视化统计】
  • 基于flet的一款windows桌面应用,实现了浏览图片、音乐、小说、各种资源的功能
  • 【开题答辩过程】以《基于微信小程序的线上讲座管理系统》为例,不会开题答辩的可以进来看看
  • 怎么做好网站建设新手怎么开传媒公司
  • 2025年8月AGI月评|AI开源项目全解析:从智能体到3D世界,技术边界再突破