- 博客(247)
- 收藏
- 关注
原创 25秋招Spring八股文
IOC 是一种设计思想。**IOC 容器是 Spring 用来实现 IOC 的载体, IOC 容器在某种程度上就是个Map(key,value),key是 name 属性,value 是对应的对象。**容器创建 Bean 对象, 使用依赖注入来管理对象之间的相互依赖关系,配置它们并管理它们的完整生命周期,很大程度上简化应用的开发,降低了耦合度。容器通过读取提供的配置,比如 XML,注解或 Java 代码来接收对象信息进行实例化,配置和组装。
2024-11-03 13:09:04
824
1
原创 2024全网最全synchronized详解专题(25秋招走起~)
示例1@Override// 同步代码块形式——锁为this,两个线程使用的锁是一样的,线程1必须要等到线程0释放了该锁后,才能执行System.out.println("我是线程" + Thread.currentThread().getName());try {System.out.println(Thread.currentThread().getName() + "结束");t1.start();t2.start();我是线程Thread-0Thread-0结束。
2024-08-13 14:36:39
744
原创 2024全网最全Java中所有的锁专题(25秋招走起~)
Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8和Netty 3.10.6)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。本文Java中常用的锁以及常见的锁的概念进行了基本介绍,并从源码以及实际应用的角度进行了对比分析。
2024-08-13 14:35:50
1020
原创 2024全网最全线程池使用的十个坑专题(25秋招走起~)
这是因为newFixedThreadPool使用了无界的阻塞队列的LinkedBlockingQueue,如果线程获取一个任务后,任务的执行时间比较长(比如,上面demo代码设置了10秒),会导致队列的任务越积越多,导致机器内存使用不停飙升, 最终出现OOM。同时,线程池最好也设计成单例模式,给它一个好的命名,以方便排查问题。按理说,每次获取的before应该都是null,但是呢,程序运行在 Tomcat 中,执行程序的线程是Tomcat的工作线程,而Tomcat的工作线程是基于线程池的。
2024-08-13 14:33:51
182
原创 2024全网最全虚拟线程原理及性能分析专题(25秋招走起~)
一、背景二、为了提升吞吐性能,我们所做的优化1. 串行模式2. 线程池 +Future 异步调用3. 线程池 +CompletableFuture 异步调用三、一请求一线程的模型四、虚拟线程1. 线程术语定义2. 虚拟线程定义3. 虚拟线程创建4. 虚拟线程实现原理5. 虚拟线程内存占用评估6. 虚拟线程的局限及使用建议7. 虚拟线程适用场景五、虚拟线程压测性能分析1. 测试流程2. 衡量指标3. Tomcat+普通线程池4. WebFlux。
2024-08-13 14:33:18
1238
原创 2024全网最全VirtualThread专题(25秋招走起~)
●虚拟线程中任务执行时候首次调用Continuation#run()执行了部分任务代码,然后尝试获取锁,会导致Continuation的yield操作让出控制权(任务切换),也就是unmount,运载线程栈数据会移动到Continuation栈的数据帧中,保存在堆内存,虚拟线程任务完成(但是虚拟线程没有终结,同时其Continuation也没有终结和释放),运载线程被释放到执行器中等待新的任务;可以看到最终效果,虚拟线程中的任务最终在自定义线程池中的唯一平台线程中运行。
2024-08-13 14:32:46
214
原创 2024全网最全completablefuture专题(25秋招走起~)
如果从堆的根节点开始从上到下按层遍历,并且每层从左到右将每个节点按照 0、1、2 等的顺序编号,将编号为 0 的节点放入数组中下标为 0 的位置,编号为1的节点放入数组中下标为1的位置,以此类推就可以将堆的所有节点都添加到数组中。上图(a)中的堆可以用数组表示成下图(a)所示的形式,而上图(b)中的堆可以用数组表示成下图(b)所示的形式。堆的插入操作可能需要交换节点,以便把节点放到合适的位置,交换的次数最多为二叉树的深度,因此如果堆中有 n 个节点,那么它的插入操作的时间复杂度是 O(logn)。
2024-08-13 14:32:12
877
原创 2024全网最全InndoDB 专题(25秋招走起~)
数据表的主键列使用的就是主键索引。一张数据表有只能有一个主键,并且主键不能为 null,不能重复。在 MySQL 的 InnoDB 的表中,当没有显示的指定表的主键时,InnoDB 会自动先检查表中是否有唯一索引的字段,如果有,则选择该字段为默认的主键,否则 InnoDB 将会自动创建一个 6Byte 的自增主键。
2024-08-13 14:31:10
770
原创 2024全网最全异步方式专题(25秋招走起~)
调用方在调用过程中,持续阻塞,一直到返回结果。同步获取结果的方式是: 主动等待。调用方在调用过程中,不会阻塞, 不直接等待返回结果, 而是执行其他任务。异步获取结果的方式是 : 被动通知或者 被动回调。1、定义发送事件对象2、定义事件监听器可以添加条件condition,限制监听具体的事件@Slf4j@Componenttry {// 休眠5秒3、定义发送接口以及实现类@Service@Resource@Override。
2024-08-13 14:30:32
824
原创 2024全网最全线程池专题(25秋招走起~)
所以,在我们调用了shutdown方法后,线程池就知道了 停止线程池的意图;否则,这一个线程修改线程池状态为TIDYING,修改线程状态为TERMINATED,调用terminated()方法,唤醒等待pool终止的线程 ,也就是awaitTermination() 的线程。状态(4)TIDYING:所有任务都已终止,线程数为0,在转向TIDYING状态的过程中,线程会执行terminated()钩子方法,钩子方法是指在本类中是空方法,而在子类中进行具体实现的方法;
2024-08-13 14:29:50
1034
原创 2024全网最Mpsc 无锁队列专题(25秋招走起~)
MpscQueue由一系列数组构成,数组的最后一个元素指向下一个数组,形成单向链表。MpscQueue全程无锁化,非阻塞,相较于JDK提供的同步阻塞队列,性能有很好的提升,这也是Netty后来的版本将任务队列替换为JCtools的重要原因。在生产过程中,它用到了大量的CAS操作,对于需要做并发控制的地方,确保只有一个线程会执行成功,其他CAS失败的线程会自旋重试,全程都是无锁非阻塞的。不管是扩容,还是等待元素被填充到数组,这些过程都是会极快完成的,因此短暂的自旋会比线程挂起再唤醒效率更高。
2024-08-13 14:29:11
1212
原创 2024全网最全volatile专题(25秋招走起~)
可见性就是指当一个线程修改了共享变量的值时,其他线程能够立即得知这个修改。指令重排是指JVM在编译Java代码的时候,或者CPU在执行JVM字节码的时候,对现有的指令顺序进行重新排序。
2024-08-13 14:28:19
1091
原创 2024全网最全系统的最佳线程数专题(25秋招走起~)
第一类:IO 密集型线程池线程数预估第二类:CPU密集线程池线程数预估第三类:混合型线程池线程数预估第一个维度:可监控预警第二个维度:可在线调整1.结合Nacos 实现动态化线程池架构3.线程池配置和nacos配置变更监听4.线程池配置的动态刷新5.LinkedBlockingQueue 实现resize。
2024-08-13 14:27:27
941
原创 2024全网最全Java8 - 多线程专题(25秋招走起~)
临界区死锁(Deadlock)是指两个或多个进程或线程在竞争资源时,因彼此之间的互斥和等待而陷入无限等待的状态,导致它们都无法继续执行下去。死锁是一种程序设计或系统管理的错误,它会导致应用程序无响应或进程挂起,需要手动干预才能解决。互斥条件至少有一个资源是独占的,即一次只能被一个进程或线程占用。如果多个进程或线程同时需要访问这个资源,就会出现互斥条件。请求与保持条件进程或线程在持有至少一个资源的同时,又请求其他资源,但无法立即获得所需资源。这就会导致持有资源的进程或线程等待其他资源的释放,形成循环等待。
2024-08-13 14:26:09
677
原创 2024全网最全ThreadLocal专题(25秋招走起~)
图中我们可以看到由于threadLocal对象是弱引用,如果外部没有强引用指向的话,它就会被GC回收,那么这个时候导致Entry的key就为NULL,如果此时value外部也没有强引用指向的话,那么这个value就永远无法访问了,按道理也该被回收。ThreadLocal采用了空间换时间的设计思想,也就是说每个线程里面都有一个专门的容器来存储共享变量的副本信息,然后每个线程只对自己的变量副本做相对应的更新操作,这样避免了多线程锁竞争的开销。关于这些引用的强弱,稍微聊一下,这里其实涉及到jvm的回收机制。
2024-08-12 14:20:58
382
原创 2024全网最全ArrayList扩容机制专题(25秋招走起~)
ArrayList 就实现了 List 接口,其实就是一个数组列表,不过作为 Java 的集合框架,它只能存储对象引用类型,也就是说当我们需要装载的数据是诸如 int、float 等基本数据类型的时候,必须把它们转换成对应的包装类。OK,首先,既然咱真正存储数据的地方是数组,那我们初始化 ArrayList 的时候自然要给数组分配一个大小,开辟一个内存空间。OK,扩容发生在啥时候?既然它是基于数组实现的,数组在内存空间中是连续分配的,那必然查询速率非常快,不过当然也肯定逃不过增删效率低的缺陷。
2024-08-12 14:19:09
360
原创 2024全网最全WeakHashMap专题(25秋招走起~)
在Java集合框架系列文章的最后,笔者打算介绍一个特殊的成员:,从名字可以看出它是某种Map。它的特殊之处在于里的entry可能会被GC自动删除,即使程序员没有调用remove()或者clear()方法。更直观的说,当使用调用两次size()方法返回不同的值;两次调用isEmpty()方法,第一次返回false,第二次返回true;两次调用containsKey()方法,第一次返回true,第二次返回false,尽管两次使用的是同一个key;
2024-08-12 14:17:47
450
原创 2024全网最全TreeSet & TreeMap专题(25秋招走起~
之所以把TreeSet和TreeMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说TreeSet里面有一个TreeMap(适配器模式)**。因此本文将重点分析TreeMap。JavaTreeMap实现了SortedMap接口,也就是说会按照key的大小顺序对Map中的元素进行排序,key大小的评判可以通过其本身的自然顺序(natural ordering),也可以通过构造时传入的比较器(Comparator)。TreeMap。
2024-08-12 14:17:05
368
原创 2024全网最全LinkedHashSet&Map专题(25秋招走起~)专题(25秋招走起~)
具体说来,LinkedHashMap有一个子类方法protected boolean removeEldestEntry(Map.Entry<K,V> eldest),该方法的作用是告诉Map是否要删除“最老”的Entry,所谓最老就是当前Map中最早插入的Entry,如果该方法返回true,最老的那个元素就会被删除。查找过程跟get()方法类似。1从table的角度看,新的entry需要插入到对应的bucket里,当有哈希冲突时,采用头插法将新的entry插入到冲突链表的头部。
2024-08-12 14:15:38
449
原创 2024全网最全HashSet & HashMap专题(25秋招走起~)专题(25秋招走起~)
上图中hash(k)&(table.length-1)等价于hash(k)%table.length,原因是HashMap要求table.length必须是2的指数,因此table.length-1就是二进制低位全是1,跟hash(k)相与会将哈希值的高位全抹掉,剩下的就是余数了。根据 Java7 HashMap 的介绍,我们知道,查找的时候,根据 hash 值我们能够快速定位到数组的具体下标,但是之后的话,需要顺着链表一个个比较下去才能找到我们需要的,时间复杂度取决于链表的长度,为 O(n)。
2024-08-12 14:14:47
280
原创 2024全网最全 PriorityQueue专题(25秋招走起~)
前面以JavaArrayDeque为例讲解了Stack和Queue,其实还有一种特殊的队列叫做,即优先队列。优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素)。这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序(),也可以通过构造时传入的比较器Comparator,类似于C++的仿函数)。Java中实现了Queue接口,不允许放入null元素;其通过堆实现,具体说是通过完全二叉树()实现的。
2024-08-12 14:13:57
344
原创 2024全网最全Collection - Stack & Queue专题(25秋招走起~)
Deque是"double ended queue", 表示双向的队列,英文读作"deck". Deque 继承自 Queue接口,除了支持Queue的方法之外,还支持insert, remove和examine操作,由于Deque是双向的,所以可以对队列的头和尾都进行操作,它同时也支持两组格式,一组是抛出异常的实现;addFirst(E e)的作用是在Deque的首端插入元素,也就是在head的前面插入元素,在空间足够且下标没有越界的情况下,只需要将elements[--head] = e即可。
2024-08-12 14:13:13
409
转载 2024全网最全LinkedList源码专题(25秋招走起~)
add()方法有两个版本,一个是add(E e),该方法在LinkedList的末尾插入元素,因为有last指向链表末尾,在末尾插入元素的花费是常数时间。上面代码中的node(int index)函数有一点小小的trick,因为链表双向的,可以从开始往后找,也可以从结尾往前找,具体朝那个方向找取决于条件index < (size >> 1),也即是index是靠近前端还是后端。remove(int index)使用的是下标计数, 只需要判断该index是否有元素即可,如果有则直接unlink这个node。
2024-08-12 14:12:39
95
原创 2024全网最全ArrayList 源码专题(25秋招走起~)
ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同步外,其余跟Vector大致相同。每个ArrayList都有一个容量(capacity),表示底层数组的实际大小,容器内存储元素的个数不能多于当前容量。当向容器中添加元素时,如果容量不足,容器会自动增大底层数组的大小。前面已经提过,Java泛型只是编译器提供的语法糖,所以这里的数组是一个Object数组,以便能够容纳任何类型的对象。
2024-08-12 14:10:48
309
原创 2024全网最全Collection 类关系图专题(25秋招走起~)
容器,就是可以容纳其他Java对象的对象。降低编程难度提高程序性能提高API间的互操作性降低学习难度降低设计和实现相关API的难度增加程序的重用性Java容器里只能放对象,对于基本类型(int, long, float, double等),需要将其包装成对象类型后(Integer, Long, Float, Double等)才能放到容器里。很多时候拆包装和解包装能够自动完成。这虽然会导致额外的性能和空间开销,但简化了设计和编程。
2024-08-12 14:10:08
365
原创 2024全网最全HashMap的时间复杂度专题(25秋招走起~)
和put操作的流程很类似, 需要从 计算key的hashcode,得到key的bucket 桶的槽位,然后通过 equals方法,在桶的链表或者红黑树里边,一个一个的比较,找到 equals方法为true的为主。时间复杂度O(1)+O(n)=O(n)。通过上面的分析,我们可以得出结论,HashMap新增元素的时间复杂度是不固定的,可能的值有O(1)、O(logn)、O(n)。通过上面的分析,我们可以得出结论,HashMap获取元素的时间复杂度是不固定的,可能的值有O(1)、O(logn)、O(n)。
2024-08-12 14:09:25
669
原创 2024全网最全JDK1.8将HashMap 头插法 改 尾插法专题(25秋招走起~)
HashMap是Java中的一种基于哈希表实现的,它允许我们使用键值对的形式来存储和获取数据。从根本上来说,一个哈希表包含一个数组,但是元素访问不是通过 index 编号的形式(比如 array[i]的形式),而是通过特殊的关键码(也就是key)来访问数组中的元素。存放Value的时候,通过一个哈希函数,通过 **关键码(key)**进行哈希运算得到哈希值,然后得到映射到(map到)的位置, 去存放值 ,读取Value的时候,也是通过同一个哈希函数。
2024-08-12 14:08:30
432
原创 2024全网最全手写hashmap专题(25秋招走起~)
首先,我们需要的是确定HashMap结构,那么咱们就定义一个Map接口和一个Map实现类HashMap,其结构如下:手写HashMap结构。
2024-08-12 14:07:38
427
原创 2024全网最全HashMap有几种遍历方法?推荐使用哪种?说一下HashMap底层实现?专题(25秋招走起~)
本文介绍了 7 种 HashMap 的遍历方式,其中 JDK 8 之前主要使用 EntrySet 和 KeySet 的遍历方式,而 KeySet 的遍历方式性能比较低,一般不推荐使用。然而在 JDK 8 之后遍历方式就有了新的选择,可以使用比较简洁的 Lambda 遍历,也可以使用性能比较高的 Stream 多线程遍历。
2024-08-12 14:06:16
348
原创 2024全网最全Java Map专题(25秋招走起~)
最近几天看了几篇有关于Java Map的外国博文,写得非常不错,所以整理了Java map 应该掌握的8个问题,都是日常开发司空见惯的问题,希望对大家有帮助;本章节所有代码demo已上传github。
2024-08-11 22:14:01
309
原创 2024全网最全Java枚举专题(25秋招走起~)
春节来临之际,祝大家新年快乐。整理了Java枚举的相关知识,算是比较基础的,希望大家一起学习进步。本章节所有代码demo已上传github。
2024-08-11 22:13:28
477
原创 2024全网最全Java基础篇专题(25秋招走起~)
一文读懂线程池的工作原理(故事白话文) Synchronized解析——如果你愿意一层一层剥开我的心 异步编程利器:CompletableFuture详解 Java日常开发的21个坑,你踩过几个? 一份Java程序员的珍藏书单,请您注意查收 Java程序员必备基础:JDK 5-15都有哪些经典新特性 程序员必备基础:Git 命令全方位学习 给你的Java程序拍个片子吧:jstack命令解析 Java程序员必备基础结构图 Java程序员必备:序列化全方位解析 优化if-else代码的八种方
2024-08-11 22:12:57
339
原创 2024全网最全jstack专题(25秋招走起~)
如果有一天,你的Java程序长时间停顿,也许是它病了,需要用jstack拍个片子分析分析,才能诊断具体什么病症,是死锁综合征,还是死循环等其他病症,本文我们一起来学习jstack命令~jstack 的功能jstack用法线程状态等基础回顾实战案例1:jstack 分析死锁实战案例2:jstack 分析CPU 过高jstack用于生成线程快照的,我们分析线程的情况,需要复习一下线程状态吧,拿小凳子坐好,复习一下啦~New:创建后尚未启动的线程处于这种状态,不会出现在Dump中。
2024-08-11 22:12:21
321
原创 2024全网最全Java序列化专题(25秋招走起~)
相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~什么是Java序列化?为什么需要序列化?序列化用途Java序列化常用API序列化的使用序列化底层日常开发序列化的注意点序列化常见面试题序列化:把Java对象转换为字节序列的过程反序列:把字节序列恢复为Java对象的过程可以的。
2024-08-11 22:11:48
317
原创 2024全网最全if-else代码优化的八种方案专题(25秋招走起~)
代码中如果if-else比较多,阅读起来比较困难,维护起来也比较困难,很容易出bug,接下来,本文将介绍优化if-else代码的八种方案。
2024-08-11 22:11:17
402
原创 2024全网最全Java8 - volatile全方位解析专题(25秋招走起~)
volatile是Java程序员必备的基础,也是面试官非常喜欢问的一个话题,本文跟大家一起开启volatile学习之旅,如果有不正确的地方,也麻烦大家指出哈,一起相互学习~1.volatile的用法2.volatile变量的作用3.现代计算机的内存模型(计算机模型,总线,MESI协议,嗅探技术)4.Java内存模型(JMM)5.并发编程的3个特性(原子性、可见性、有序性、happen-before、as-if-serial、指令重排)
2024-08-11 22:10:37
370
原创 2024全网最全异常的十个关键知识点专题(25秋招走起~)
总结了Java异常十个关键知识点,面试或者工作中都有用哦,加油。自定义异常通常是定义一个继承自 Exception 类的子类。那么,为什么需要自定义异常?Java提供的异常体系不可能预见所有的错误。业务开发中,使用自定义异常,可以让项目代码更加规范,也便于管理。下面是我司自定义异常类的一个简单demo//错误信息//错误码@Override跑个main方测试一下throw new BizException("100","哥,我错了");try {
2024-08-11 22:09:47
370
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人