Java集合源码:(五) HashMap 红黑树(JDK8)

HashMap在hash冲突后会形成链表,然后链表元素超过8时就会转换成红黑树。今天就是要来研究下红黑树的。 红黑树算法 红黑树也叫自平衡二叉查找树或者平衡二叉B树,时间复杂度为O(log n) ,高度h <= log2(n+1)。红黑树是建立在二叉查找树的基础之上的,二叉查找树又是建立在二叉树的基础之上。所以,我们需要从二叉树开始学习红黑树的发展脉络。

查看详情

Java集合源码:(二) LinkedList源码解析(JDK8)

LinkedList 底层是双向链表,它的增删只需要移动指针即可,故时间效率较高。不需要批量扩容,也不需要预留空间,所以空间效率比ArrayList高。 缺点就是需要随机访问元素时,时间效率很低,虽然底层在根据下标查询Node的时候,会根据index判断目标Node在前半段还是后半段,然后决定是顺序还是逆序查询,以提升时间效率。不过随着n的增大,总体时间效率依然很低。

查看详情

Java集合源码:(一) ArrayList源码解析(JDK8)

ArrayList概述 ArrayList 是一个动态数组,它是线程不安全的,允许元素为null。底层数据结构依然是数组,它是占据一块连续的内存空间(容量就是数组的length),所以它也有数组的缺点,空间效率不高。由于数组的内存连续,可以根据下标以O1的时间读写(改查)元素,因此时间效率很高。

查看详情

Java集合 最全工具

集合工具在以后公司开发必不可少,必须要牢牢掌握! 本文主要讲两个工具: Collections工具 Apache Commons Collections CollectionUtils 工具 在今后的开发中,麻烦首先想到这些工具,不要重复造轮子。。。

查看详情

Java 动态代理 Proxy源码详解

代理简介? 我们知道nginx可以实现正向,反向代理。比如我们想请求服务中一个tomcat,一般就是直接访问机器的ip,如果是代理的话,就是先访问中间代理层(nginx),然后nignx跳转到我们的tomcat机器。代理模式也是如此,也有一个Proxy层,通过Proxy层来真正访问我们的类接口。

查看详情

Java SPI+Dubbo SPI+SpringBoot SPI 原理解析

一、SPI 是什么? SPI(Service Provider Interface):是一个可以被第三方扩展或实现的 API,它可以用来实现框架扩展和可替换的模块,优势是实现解耦。简单来说就是推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。若在代码里涉及具体的实现类就违反了可挺拔的原则。从而 java SPI 提供了这种服务发现机制:为某个接口寻找服务实现的机制。

查看详情

Java 反射基本使用+使用案例

介绍反射基础且常用方法 , 和自己写一些反射的案例, 这个可是架构师本领的必须技能: 案例一 : 反射实现SPI。 案例二: 反射实现自动生成Controller接口文档。 反射定义 反射允许我们在运行时获取类、接口、字段和方法 , 并且可以进行修改。如果要写框架代码必须要掌握!

查看详情

CountDownLatch 遇到 线程池 卡死

更加验证了我的猜想,就是线程池直接抛弃了任务,导致 countDownLatch.countDown() 减减 不到 构造时候的值,从而造成阻塞,卡死。 大家还是慎用这个 DiscardPolicy 策略,很难找到问题的。 整改 调整了下线程池的队列大小到20000 ,实际量远远达不到。然后将拒绝策略改成默认的AbortPolicy 。然后上线,没问题了~~万事大吉!

查看详情

Java 线程池 ThreadPoolExecutor 原理

为什么要使用线程池 平时讨论多线程处理,大佬们必定会说使用线程池,那为什么要使用线程池?其实,这个问题可以反过来思考一下,不使用线程池会怎么样?当需要多线程并发执行任务时,只能不断的通过new Thread创建线程,每创建一个线程都需要在堆上分配内存空间,同时需要分配虚拟机栈...

查看详情

AQS (2) 共享锁 CountDownLatch 源码分析

前面提到过独占锁的实现,今天来讲下共享锁。来看下定义: 独占锁被某个线程持有时,其他线程只能等待当前线程释放后才能去竞争锁,而且只有一个线程能竞争锁成功。 共享锁是可以被共享的,它可以被多个线程同时持有。如果一个线程获取共享锁成功,那么其他等待的线程也会去获取共享锁,而且获取大概率会成功。共享锁典型的有ReadWriteLock、CountdownLatch。

查看详情

AQS (1) ReentrantLock 的上锁 与 解锁 源码

AQS( java.util.concurrent.locks.AbstractQueuedSynchronizer ) , AQS可以说是整个Java并发编程包JUC的底层实现,采用CAS+自旋的方式,然后采用一个双向链表组成的队列,结合一个state来实现的同步器。很多JUC包,比如ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier 都是通过AQS来实现的。也就是说AQS主要用来: 提供多线程竞争时,线程等待唤醒的机制,也就是如何用java应用层代码实现锁。

查看详情

Java锁架构

java提供了很多锁的实现,有的是在jvm层面实现的,有的是在rt.jar中实现的。今天我们来大致讲解下有哪些锁,以及简单的思想。 乐观锁 & 悲观锁

查看详情

java线程堆栈 分析

java线程start方法最终都追踪到native start0方法上,该方法通过jni机制,首先在C++层面创建了JavaThread对象,然后在JavaThread的构造里面通过c函数 pthread_create 创建了系统级别的线程。因此java线程和系统线程是一个一对一的关系。

查看详情

JMM+Volatile 理论

CPU 高速缓存(CPU Cache) CPU的频率太快,快到主存跟不上,这样在处理器时钟周期内,CPU经常需要等待主存,浪费资源。所以缓存的出现,是为了缓解CPU和内存间速度的不匹配问题。(结论:CPU>缓存>主存) 当CPU要读取一个数据时,首先从一级缓存中查找,如果没有找到再从二级缓存中查找,如果还是没有就从三级缓存或内存中查找。

查看详情

Java Thread源码分析

线程组 线程组ThreadGroup表示一组线程的集合,一旦一个线程归属到一个线程组之中后,就不能再更换其所在的线程组。那么为什么要使用线程组呢?个人认为有以下的好处:方便统一管理,线程组可以进行复制,快速定位到一个线程,统一进行异常设置等。

查看详情

CPU的工作过程

CPU的基本工作是执行存储的指令序列,即程序。程序的执行过程实际上是不断地取出指令、分析指令、执行指令的过程。 CPU从存放程序的主存储器里取出一条指令,译码并执行这条指令,保存执行结果,紧接着又去取指令,译码,执行指令……,如此周而复始,反复循环,使得计算机能够自动地工作。除非遇到停机指令,否则这个循环将一直进行下去。其过程如图3-3所示

查看详情

Linux线程理论

线程是操作系统能够调度和执行的基本单位,在Linux中也被称之为轻量级进程。线程只是一个与其他进程共享某些资源的进程。每一个线程拥有一个唯一的task_struct结构,Linux内核它仅仅把线程当做一个正常的进程,或者说是轻量级进程,LWP(Lightweight processes)。

查看详情

Java Throwable 源码解析

fillInStackTrace 方法时加锁的,并且会执行native方法,因此多线程环境下性能很差。我们有时new自己定义的业务异常时,且用不到堆栈,但是会调用这个方法,严重影响系统性能。下面看个实例:

查看详情

Java异常正确使用方式

有时,您可能希望将异常包装在另一个异常中。单千万不要搞丢原始的异常堆栈。Exception类及其所有子类提供了几个构造函数方法,这些方法接受原始异常作为参数并将其设置为原因。 如下面代码:

查看详情

try catch 底层原理

当一个异常发生时,JVM会在当前出现异常的方法中,查找异常表,是否有合适的处理者来处理,如果当前方法异常表不为空,并且异常符合处理者的from和to节点,并且type也匹配,则JVM调用位于target的调用者来处理。 如果上一条未找到合理的处理者,则继续查找异常表中的剩余条目。

查看详情