ThreadLocal底层实现原理详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、ThreadLocal简介ThreadLocal顾名思义可以根据字面意思理解成线程本地变量。也就是说如果定义了一个ThreadLocal,每个线程都可以在这个ThreadLocal中读写,这个读写是线程隔离的,线程之前不会有影响。
每个Thread都维护自己的一个ThreadLocalMap ,所以是线程隔离的。
123/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;
通过这个ThreadLocalMap实现数据的读写,既然是Map肯定有key和value,但是这个ThreadLocalMap的key可以简单的看成是ThreadLocal,实际是并不是ThreadLocal的本身,而是它的一个弱引用。
二、ThreadLocal学习大纲学习大纲思维导图如下 ...
Java锁(三):Semaphore共享锁详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、基于AQS实现的锁AQS(AbstractQueuedSynchronizer) 是Java并发包JUC中非常重要的一个类,大部分锁都是基于AQS实现的,主要实现的类如下:
ReentrantLock:可重入锁,独占锁,实现了公平锁和非公平锁,这个是上篇内容介绍的类,也是最常用类,通常会和synchronized作比较。
ReentrantReadWriteLock:读写锁,可共享也可独占锁,读是共享锁,写是独占锁,也实现了公平锁和非公平锁。
Semaphore:信号锁,共享锁,也实现了公平锁和非公平锁,主要同于控制流量,比如:数据库连接池给你分配10个链接,来一个分配一个,如果10个都分配完了且没有释放那就等待释放。
CountDownLatch:闭锁,共享锁,也实现了公平锁和非公平锁,Latch门闩的意思,比如:说四个人一个漂流艇,坐满了就推下水。
二、SemaphoreSemaphore是什么上面已经介绍了Semaphore,基于AQS实现的信号锁,是共享锁,实现了公平锁和非公平锁。 ...
Java锁(二):AbstractQueuedSynchronizer、ReentrantLock详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、AbstractQueuedSynchronizer简介AQS(AbstractQueuedSynchronizer)是并发容器JUC(java.util.concurrent)下locks包内的一个抽象类,是一个同步器,是用来构建锁或者其他同步组件的基础框架,内部维护了一个成员变量state表示同步状态,state=0表示线程未获取到锁,state > 0表示获取到锁,state > 1表示重入锁的数量,被 volatile修饰保证了可见性,通过CAS操作对其修改,内置维护了FIFO队列实现对未获取到锁的线程进行排队工作。
二、AbstractQueuedSynchronizer源码解析核心成员变量123456789101112131415161718192021222324public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.S ...
Java锁(一):volatile、synchronized详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、锁的基础知识锁的类型锁从客观上分为悲观锁和乐观锁。
乐观锁:乐观锁是一种乐观思想,认为写少读多,遇到并发写的可能性比较低,读数据的时候认为别人不会修改,所以读的时候不会上锁,但是在写的时候会判断一下在此期间有没有别人去更新这个数据,采取的是先读取当前版本号,然后加锁操作,写完的时候读取最新版本号做记录的版本号做比较一样则成功,如果失败则重复读-比较-写的操作。Java中的乐观锁基本都是通过CAS操作实现的,java.util.concurrent.atomic包下的原子变量。CAS(compare and swap)比较交换是一种更新的原子操作,比较当前值和传入值是否一样,一样则更新,否则则失败。
悲观锁:悲观锁就是悲观思想,认为写多且遇到并发性的可能性高,每次拿数据的时候都认为别人为修改,所以每次读写的时候都会上锁,这样别人想读写数据的时候都会block(阻塞)知道拿到锁。Java中悲观锁就是syschronized,AQS框架下的锁则是先尝试CAS乐观锁获取锁,如果获取不到,才会转为悲观锁,如Re ...
JVM-GC垃圾回收
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
学习JVM垃圾回收机制主要学习以下几点:哪些内存需要回收(判断对象可以回收)、什么时候回收(GC什么时候执行)、怎么回收(垃圾回收算法、垃圾回收器)、垃圾回收过程。
JVM GC回收哪些区域内的垃圾?JVM GC只回收堆区和方法区内的对象,不回收虚拟机栈内的数据,栈内数据在超出作用域后会被JVM自动释放掉。
因为JVM GC回收堆区的对象,所以先了解学习一下堆内存的结构图:
堆内存分为年轻代(Young Generation)、老年代(Old Generation),年轻代和老年代所占空间比例默认是1:2。年轻代又分为Eden和Survivor区,Survivor区由FormSpace和ToSpace组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1。From和To主要是为了解决内存碎片化。
JVM GC怎么判断对象可以回收?
对象没有引用。
作用域发生未捕获异常。
程序在作用域正常执行完毕。
程序执行了System.exit()。
程序发生意外终止(被杀进程等)。
判断对象是 ...
六大设计模式原则-依赖倒置原则
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、依赖倒置原则定义依赖倒置原则:抽象不应该依赖于实现,实现应该依赖于抽象,也就是说我们应该面对抽象(接口)编程,而不应该面对实现编程。
二、依赖倒置原则描述依赖倒置原则要求我们在程序代码中传递参数或在关联关系时,尽量引用高层次类抽象类(接口类),而不应该引用具体的实现类,即使用抽象类或者接口进行变量类型声明、参数类型声明、方法返回结果声明。
在引用抽象层之后,系统将得到很好的灵活性,抽象类无需改变,只需新增新的实现类即可,也满足了开闭原则。
三、依赖倒置原则示例场景现有一个抽奖策略的设计,在不使用设计模式时,设计了一个DrawControl抽奖控制类,这个类里面包含了doDrawRandom()、doDrawWeight()两种抽奖策略,这种设计在实际开发起来速度是非常快的,但是后续不好维护,如果后续要新增其他的抽奖策略该类就要新增方法不利于维护也不满足开闭原则。
123456789public class DrawControl { public List<BetUser> ...
JVM-类加载详解
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、JVM类加载过程JVM类加载过程如下图:
JVM类加载过程分为:加载 、链接 、初始化 、使用 、卸载 这五个阶段,其中链接阶段又包括:验证 、准备 、解析 。
加载 :通过类的完全限定名,查找此类的二进制字节码文件,通过该字节码文件创建Class对象。
链接 :包含验证 、准备 、解析 三个阶段:
验证 :确保Class文件复合虚拟机规定的Class文件格式,包含文件格式验证、元数据验证、字节码验证、引用符号验证。
准备 :为类的静态变量分配内存并设置初始化值,注:这里不包含`final`修饰的静态变量,因为`final`修饰的静态变量是在编译期分配。
解析 :将常量池的间接引用转换为直接引用,解析包含字段解析、接口解析、方法解析。
初始化 :初始化静态变量和静态块,先初始化父类,再初始化当前类,只有对类主动时才会初始化。
使用 :程序代码执行时使用,new出对象程序中使用。
卸载 :程序代码退出、异常、结束等,执行垃圾回收。
二、类加载时机
创建类的实例,也就是new一个对象。
访问类 ...
六大设计模式原则-接口隔离原则
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、接口隔离原则定义接口隔离原则定义如下:
接口隔离原则(Interface Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。
二、接口隔离原则描述根绝接口隔离原则,当一个接口太大时,我们需要将它分割成一些细小的接口,使用该接口的客户端只需知道与之相关的方法即可。每一个接口应该承担一种相对独立的角色,不干不该干的事情,干该干的事请。这里的”接口”往往有两种不同的定义:一种是指一个类型所具有的方法特征的集合,仅仅是一种逻辑上的抽象;另外一种是某种语言上具体的”接口”定义,比如Java语言的interface。对于这两种不同的含义,接口隔离原则表达以及含义所以不同:
当把”接口“理解成一个类型所具有的方法特性的集合时,就是一种逻辑上的概念,接口的划分将直接带来类的划分。可以把接口理解成角色,一个接口只能代表一个角色,每个角色都有它特定一个接口,此时这个原则可以叫做角色隔离原则。
如果把”接口”理解成狭义的特定语言接口,那么 ...
六大设计模式原则-迪米特法则
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、迪米特法则定义迪米特法则又最少知识原则,其定义如下:
迪米特法则(Law of Demeter, LoD):一个软件实体应当尽可能少的与其他实体发生相互作用。
二、迪米特法则描述如果一个系统满足迪米特法则,那么当其中一个软件实体发生变化时,就会尽量少的影响其他软件实体,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。迪米特法则可以降低系统的耦合度,使类与类之间保持松耦合状态。
迪米特法则还有几种定义形式,包括:不要和”陌生人”说话、只与你的直接朋友通信等,在迪米特法则中,对于一个对象,其朋友包括以下几类:
当前对象本身(this)
以参数形式传入到当前对象方法中的对象
当前对象的成员对象
如果当前对象的成员对象是一个集合,那么集合中的元素也都是朋友。
当前对象创建的对象
任何一个对象,如果满足上面的条件之一,就是当前对象的“朋友”,否则就是“陌生人”。在应用迪米特法则时,一个对象只能与直接朋友发生交互,不能与“陌生人”发生直接交互,这样子可以降低系统的耦 ...
JVM-内存模型
热衷学习,热衷生活!😄
沉淀、分享、成长,让自己和他人都能有所收获!😄
一、JDK1.6、JDK1.7、JDK1.8内存模型演变JDK1.6、JDK1.7、JDK1.8内存模型演变规程如下图:
从上图我们可以看出这些版本的JVM内存模型主要有以下差异:
JDK1.6:有永久代,静态变量存放在永久代(方法区)。
JDK1.7:有永久代,但是已经把字符串常量池、静态变量存放到堆中,逐渐减少永久代的使用。
JDK1.8:无永久代,运行时常量池、类常量池都保存到元数据区,也就是常说的元空间。但字符串常量池仍存在堆中。
二、JVM运行时内存区域概述JVM在运行时Java程序时,会把管理的内存划分为若干个区域,每个区域都有自己的用途和创建销毁时间。如下图所示,可以分为两大部分,线程私有区域和线程共享区域。线程私有区域包括:虚拟机栈、本地方法栈、程序计数器,线程共享区域包括:Java堆、方法区。
线程私有区域虚拟机栈线程私有的,与线程同一时间创建,管理Java方法执行时的内存模式。每个方法执行的时候都会创建一个帧栈来储存方法的局部变量表、操作数帧、动态链接方法、返回值、返回地址等信息 ...