注册域名后如何建立网站,上海城隍庙必吃美食,nginx php wordpress,如何制作表白小程序ThreadLocal 线程变量存放在当前线程变量中#xff0c;线程上下文中#xff0c;set将变量添加到threadLocals变量中 Thread类中定义了两个ThreadLocalMap类型变量threadLocals、inheritableThreadLocals用来存储当前操作的ThreadLocal的引用及变量对象#xff0c;把当前线程…ThreadLocal 线程变量存放在当前线程变量中线程上下文中set将变量添加到threadLocals变量中 Thread类中定义了两个ThreadLocalMap类型变量threadLocals、inheritableThreadLocals用来存储当前操作的ThreadLocal的引用及变量对象把当前线程的变量和其他的线程的变量之间进行隔离从而实现了线程的安全性 InheritableThreadLocal类重写get/set方法会对线程的inheritableThreadLocals变量初始化在对子线程初始化时将子线程的inheritableThreadLocals变量赋值为父线程的inheritableThreadLocals变量值实现了子线程继承父线程
内存泄漏问题 Thread-ThreadLocalMap-Entry-valueThreadLocalMap是继承了WeakReference的entry集合但是线程一直没有removethreadLocal下次GC将弱引用对象回收entry对象的key为nullvalue值却是强引用关系 ThreadLocal每次调用get、set、remove的时候都会直接或者间接的调用expungeStaleEntry方法清除掉key为null的Entry 主线程执行ThreadLocal.remove()后子线程中的ThreadLocal并不会被remove()判空导致线程池中维护的ThreadLocal存储的值一直不变
池化InheritableThreadLocal子线程使用线程池 更改存储 变量值不变 没找到对应的InheritableThreadLocal 自然改不了普通的ThreadLocal会让子线程获取不到get值 池化减少资源对象创建次数
private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {//省略部分代码//如果父线程inheritableThreadLocals不为空则保存下来if (inheritThreadLocals parent.inheritableThreadLocals ! null)this.inheritableThreadLocals ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);//省略部分代码
}
注意 使用静态和不使用静态时候 使用静态的InheritableThreadLocal 线程池复用时候不会有问题 ThreadLocal是线程本地变量每个线程有自己的副本InheritableThreadLocal具有继承性在创建子线程时子线程可以继承父线程的变量副本。
https://www.cnblogs.com/shanheyongmu/p/17922183.html
https://www.cnblogs.com/tiancai/p/17622821.html InheritableThreadLocal详解 - 简书
TransmittableThreadLocal
继承自InheritableThreadLocal在线程池中传递ThreadLocal变量的值
GitHub - alibaba/transmittable-thread-local: a missing Java std lib(simple 0-dependency) for framework/middleware, provide an enhanced InheritableThreadLocal that transmits values between threads even using thread pooling components.
/*
* holder里面存储所有关于TransmittableThreadLocal的引用
*/
public class TransmittableThreadLocalT extends InheritableThreadLocalT implements TtlCopierT {// 1. 此处的holder是他的主要设计点后续在构建TtlRunnableprivate static InheritableThreadLocalWeakHashMapTransmittableThreadLocalObject, ? holder new InheritableThreadLocalWeakHashMapTransmittableThreadLocalObject, ?() {Overrideprotected WeakHashMapTransmittableThreadLocalObject, ? initialValue() {return new WeakHashMapTransmittableThreadLocalObject, Object();}Overrideprotected WeakHashMapTransmittableThreadLocalObject, ? childValue(WeakHashMapTransmittableThreadLocalObject, ? parentValue) {return new WeakHashMapTransmittableThreadLocalObject, Object(parentValue);}};SuppressWarnings(unchecked)private void addThisToHolder() {if (!holder.get().containsKey(this)) {holder.get().put((TransmittableThreadLocalObject) this, null); // WeakHashMap supports null value.}}Overridepublic final T get() {T value super.get();if (disableIgnoreNullValueSemantics || null ! value) addThisToHolder();return value;}/*** see {link InheritableThreadLocal#set}*/Overridepublic final void set(T value) {if (!disableIgnoreNullValueSemantics null value) {// may set null to remove valueremove();} else {super.set(value);addThisToHolder();}}/*** see {link InheritableThreadLocal#remove()}*/Overridepublic final void remove() {removeThisFromHolder();super.remove();}private void superRemove() {super.remove();}
}
1.继承InheritableThreadLocal成立个TransmittableThreadLocal类 该类中有一个hodel变量维护所有的TransmittableThreadLocal引用。
2.在实际submit任务到线程池的时候需要调用TtlRunnable.get构建一个任务的包装类。使用装饰者模式对runnable线程对象进行包装在初始化这个包装对象的时候获取主线程里面所有的TransmittableThreadLocal引用以及里面所有的值这个值是当前父线程里面的跟你当时创建这个线程的父线程没有任何关系注意这里讲的是线程池的场景。
3.对数据做规整根据收集到的captured (这个对象里面存储的都是主线程里面能够获取到TransmittableThreadLocal以及对应的值) 做规整去掉当前线程里面不需要的同时将剩余的key和value 更新到当前线程的ThreadLocal里面。这样就达到了在池化技术里面父子线程传值的安全性
多线程篇-TransmittableThreadLocal解决池化复用线程的传值问题 - 知乎
hashMap1.7与1.8
1.7底层是entry数组链表
颠倒链表顺序 元素插入前是否需要扩容扩容后all元素重新计算下位置
头插法逆序 环形链表死循环
ReentrantLockSegmentHashEntry 第一次put hash(key)定位segment 未初始化cas赋值 第二次puthashEntry ReentrantLock.tryLock获取锁否自旋tryLock 获取锁 超次挂起
1.8node数组链表红黑树
保持原链表顺序 元素插入后检查是否扩容
链表长度达到8/元素总数达到64
synchronizedCASHashEntry红黑树 没有初始化initTable 没有hash冲突 cas插入否 加锁 链表遍历到尾部插入 红黑树就是红黑树的结构插入 添加成功addCount统计size是否需要扩容 高低位指针的形式将低位上的数据移动到原来的位置高位上的数据移动到【原来的位置旧数组容量】的位置避免了rehash
AQS
ConditionObject的await和signal等同Object的wait、notify函数(Synchronized) 五层 如果被请求的共享资源空闲将当前请求资源的线程设置为有效的工作线程将共享资源设置为锁定状态 如果共享资源被占用需要一定的阻塞等待唤醒机制来保证锁分配。这个机制主要用的是CLH队列Craig、Landin and Hagersten是单向链表的变体实现的将暂时获取不到锁的线程加入到队列中AQS是通过将每条请求共享资源的线程封装成一个节点node来实现锁的分配
理解AQS的原理及应用总结_aqs原理-CSDN博客 这篇阿里P6的水平了
CountDownLatch和CyclicBarrier
CountDownLatch放行由其他线程控制一直等待直到线程完成操作 计数器 aqscountDown减state-1await 判断state0 非加入队列阻塞 头节点自旋等待state0
CyclicBarrier本身控制线程到达状态 暂停等待其他线程all线程到达后 继续执行 任务线程调用线程相互等待可重用
ReentrantLock加上Conditionawaitcount -1 ReentrantLock线程安全性如count不为0加则condition队列中如count0把节点从condition队列添加至AQS的队列中进行全部唤醒并且将parties的值重新赋值为count的值实现复用)
volatile
共享变量主内存
线程有自己的工作内存
线程间变量的值传递需要主内存 一个线程使用共享变量先判断当前副本变量的状态 无效状态的话 向总线发送read 消息读取变量最新数据 总线贯穿这个变量用到的所有缓存以及主存 读取到的最新数据可能来自主存 也可能来自其他线程 lock指令 本地线程写入内存其他线程失效 read指令 读取变量最新数据
禁止指令重排
字节码层面使用volatile修饰变量在编译后的字节码中为变量添加ACC_VOLATILE标记 JVM层面JVM规范中有4个内存屏障LoadLoad/StoreStore/LoadStore/StoreLoad在读到ACC_VOLATILE标记时会在内存区读写之前都加屏障 操作系统和硬件层面操作系统执行该程序时查到有内存屏障使用lock指令在指令前后都加lock(屏障)保证前后不乱序
volatile 指令重排以及为什么禁止指令重排_volatile为什么要禁止重排序-CSDN博客
总线风暴
volatile和cas导致bus总线缓存一致性流量激增
一个变量在多个高速缓存中存在高速缓存间数据不共享 数据不一致 总线锁定 缓存锁定
MESI已修改modified 互斥独占exclusive 共享share 无效invalid 1使用共享数据 拷贝到1缓存中 设为E 2也使用共享数据拷贝到2缓存 1把变量回写到主存先锁住缓存行状态M 向总线发消息告诉其他 在嗅探的cpu 该变量被修改并写会主存其他CPU 状态S I无效需要时从内存获取 发现缓存地址被改了无效I
失效共享变量大于缓存行大小 mesi 无法对缓存行加锁 高速缓存时间局部性(变量被访问 近期may再次被访问) 空间局部性(变量被访问 周围变量可能被近期访问)
缓存行默认64字节
https://blog.51cto.com/u_16213606/7587478
java数据结构
树
前序遍历 ①先访问根节点 ②在访问左节点接着访问右节点
后序遍历 ①先访问左节点在访问右节点 ②最后访问根节点 二叉树 一颗非空二叉树的第i层上最多有2^(i-1)个节点 一颗高度为k的二叉树最多有2^k -1 个节点
满二叉 一颗高度为K 并且具有2^k - 1 个节点
完全二叉树
哈夫曼树
哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树
数据结构——哈夫曼树-CSDN博客
二叉排序树
左小右大
二叉平衡树AVL
左右子树 高度差 1
数据结构——常见的几种树万字解析_数据结构如何判断型lr型rr型rl型-CSDN博客
红黑树带颜色 非黑即红
二叉查找树
Trie树前缀树/字典树
从根节点到某一节点路径上经过的字符连接起来为该节点对应的字符串
B树多路平衡查找树
每个节点最多只有m个子节点
非叶子节点中不仅包含索引也会包含数据
B树
所有的叶子结点中包含了全部关键字的信息
总结下各种常见树形结构的定义及特点二叉树、AVL树、红黑树、Trie树、B树、B树 - 知乎
mysql
count1和count*
数据量大 *费时 没有主键 *慢联合主键 *比主键慢 一个字段*最快
*自动优化指定到某列字段
唯一索引和普通索引的区别
changeBufferbuffer pool一部分缓存非唯一索引当操作命中缓存中索引时 合并操作 空闲写入磁盘 减少IO 目的是减少查询索引表唯一索引校验唯一性 不得不查索引表 不能使用changeBuffer
merge过程 磁盘读取数据页到内存 changeBuffer找到数据页changeBuffer应用到新数据页 redoLog含数据变更信息changBuffer数据变更动作 Mysql - 普通索引与唯一索引之间性能差别change buffer-CSDN博客
redoLog与changeBuffer redoLog节省随机写磁盘的IO消耗 转成顺序写 changeBuffer随机读磁盘的IO消耗
唯一索引和普通索引的区别以及changeBuffer_唯一索引和普通索引区别 changebuffer-CSDN博客
普通索引和唯一索引难道还分不清 - 知乎
页分裂
我也快分裂了 什么世道 卷吧 比鸡蛋卷还
一个数据页满的情况下为插入新数据 将该页分裂为两页 新数据插入新页 减少数据迁移 提供插入效率 过程新建页 原页一半数据移动到新页 插入新数据到新页 更新原页指针指向新页 调控优化 innodb_autoinc_lock_mode 控制自增字段锁定方式2页级锁定 减少锁定粒度 提供库性能 innodb_fill_factor控制数据页填充的程度参数越小 填充程度越高 减少页分裂次数 优化查询语句 合并事务
https://blog.51cto.com/u_16175465/9573866
页合并
ibd文件segment段 extent区1M 64pages page页16k 2-N数据行 max8000bytes
merge_threshold
mysql InnoDB中的页合并与分裂_mysq页合并-CSDN博客 删除一行记录 标上flaged 且被容许使用 删除记录达到merge_threshold 页体积50% innodb寻找最靠近的页 是否可将两个合并 JVM
癫狂吧这个世界
可达性分析算法中根节点 GC管理主要是堆你像方法区 栈 本地方法区
本地方法栈中JNI native方法引用的对象
虚拟机栈(局部变量表)引用的对象
方法区类静态属性引用的对象
方法区常量引用的对象 tracingGC 通过找到活对象把其他的空间认定为无用
hotspot OopMap记录根对象引用 类加载完 hotspot会把对象内什么偏移量是什么类型的数据计算出来 特定位置 记录栈 寄存器哪些位置是引用 安全点all线程尽快在安全点停下来 GC时挂起 方法调用/循环跳转/异常跳转 安全区域内引用关系不变化 回收垃圾是安全的 记忆集记录从非收集区域指向收集区域的指针集合 YGC时老年代对象引用了新生代对象老年代加入可达性分析中 卡表:非收集区2的N次幂字节数大小区域HotSpot中是2的9次幂512字节 0无 1有 -1脏 写屏障维护卡表引用类型字段赋值前后加上前/后屏障 aop
并发的可达性分析 根节点出发 找出所有存活对象线程进入安全点或安全区域 停顿等待可达性分析完成 避免长时间停顿分为两阶段 初始标记STW(根节点all被引用对象) 和 并发标记(被引用对象出发找到后续引用对象) CMS G1
三色标记 白色 未被引用的垃圾对象 黑色已扫描过的存活对象 灰色本身存活 至少一个未扫描的引用 垃圾对象白色被重新引用对象消失 插入一条/多条黑色对象到白色的引用 同时删除灰色对象到白色对象的引用 解决 增量更新写屏障在引用变化时将相关黑色对象标记为灰色对象重新标记阶段灰色被发现 白色也被发现 存活 CMS 黑色就不扫了所以灰色强制扫 原始快照扫描生成对象图快照删除灰色对白色引用时 删除的引用记录下来 并发扫描结束后将这些变动的引用中灰色作为根 按快照图重新扫描 快照图中保存了删除前引用关系 白色扫描到标记为存活G1
垃圾收集器
年轻代收集器Serial、ParNew、Parallel Scavenge
老年代收集器Serial Old、CMS、Parallel Old
Parallel Scavenge、Parallel OldJDK8
提供jvm吞吐量STW整个流程 -XX:MaxGCPauseMillis最大停顿时间收集器尽量时间内回收越小新生代越小 回收空间小 吞吐量容易变低 -XX:GCTimeRatio(垃圾收集时间比率0-100)运行用户代码时间占比 1:19 占1%总时间 ;最大占5%的总时间
CMS
缩短GC停顿时间内存不足收集失败 就会用 serialOld单线程收集垃圾
问题 cpu核数少 垃圾回收对用户程序影响大 默认开启(处理器核心数量 3)/4 (24)/41占有50cpu资源 浮动垃圾下次GC才能回收 并发收集失败 concurrent mode failure单线程回收预留内存不足分配新对象老年代到了-XX:CMSInitiatingOccupancyFraction使用率 触发CMS 1-100越小 预留空间越大 cms越频繁 标记清除算法内存碎片开启内存整理-XX:UseCMS-CompactAtFullCollection9废弃 G1
jdk9默认物理上不分代逻辑上分代堆内存划分成N个相等大小的Region
动态指定region属于eden/survivor或老年代中的一种大对象Humongous区域
-XX:MaxGCPauseMillis最大收集停顿时间200msregion回收最小单元维护可回收region集合collectionSetg1计算回收能获得空间大小 时间 过往回收经验 按停顿时间 有计划回收高优先级收益大region region维护哈希表结构的记忆集 记录跨region引用key别的region的起始地址value存储卡表的索引号集合双向结构 TAMS指针划分region空间分配新对象默认存活不纳入回收范围 cms和G1区别
cms标记清除/g1复制清除
g1耗内存维护region记忆集合20%甚至更多内存cms只是记录跨代引用
g1负载高cms g1写屏障维护记忆集合变动的引用信息g1复杂 维护成本高 cms简单卡表
并发标记对象消失问题cms增量更新 黑变灰 g1 satb原始快照 停顿时间短
整体看小内存应用cms优shi大 6-8G
satb
Snapshot-At-The-Beginning
开始标记生成快照图标记存活对象并发标记被改变对象入队(写屏障 all旧引用指向的对象变灰) tamstop at mark start region记录prevTAMS nextTAMStasm分配新对象
JVM垃圾回收总结_可达性分析算法中根节点有哪些-CSDN博客
SATB深入详解与问题剖析【纯理论】-CSDN博客
怎样GC调优 Young GC后的存活对象小于Survivor区域50%都留存在年轻代里
jstat内存分配速率 GC次数/耗时 jstat -gc pid 时间间隔 次数
jmap运行时对象分布/内存 jmap -histo:live pid jmap -dump:live,formatb,filedump.hprof pid -XX:HeapDumpOnOutOfMemoryError. -XX:HeapDumpPathpath. -XX:HeapDumpIntervalseconds
jstack:堆栈跟踪工具 当前时刻的线程快照 jstack pid|grep -A 100 线程id(printf %x\n * )
jinfo系统参数命令启动参数 jinfo -flags pid
arthas在线诊断工具https://arthas.aliyun.com/doc/
如何进行GC调优 - 简书
FullGC触发条件
老年代空间不足新生代空间不足放到老年代老年代不足fullGC -- XX:NewRation永久代空间不足7堆MaxPermSize8本地内存MaxMetaspaceSize字符串常量池在堆中CMS碎片过多扛不住 CMSFullGCsBeforeCompaction多少次fullGC压缩堆整理碎片CMS GC时出现了promotion failed新生代把对象扔老年代老年代不行和concurrent mode failure启动老年代内存占比阈值高预留空间不足担保机制老年代增长过快触发full gc进行清理CMSInitiatingOccupancyFraction降低触发CMS的阀值system.gc建议系统调用fullGC -XX:-DisableExplicitGC禁止此类full gc新生代minor gc时晋升到老年代的平均大小大于老生代剩余空间
大对象对象池技术 重复利用对象 分配从堆移动到本地内存 对象池的介绍与使用-CSDN博客
怎样排查CPU彪高
监控cpu使用率top taskManager jstat
线程分析jstack
关联分析线程转储与CPU占用线程的操作系统id关联ps -L -p pid进程中的线程 进程
代码分析死循环 大量循环计算 密集字符串操作
性能剖析visualVM YourKit JProfiler实时监控
Java CPU或内存使用率过高问题定位教程_java内存和cpu飙升-CSDN博客
Prometheus如何收集数据
基于时间序列数据库的监控系统
拉取pull定期拉取监控数据默认推送push目标主动将监控数据推送到服务器服务发现支持多种服务发现机制 Consul, DNS, Kubernetes自动发现需要监控的目标集成第三方 Graphite, InfluxDB, Elasticsearch 等
克服网络障碍Prometheus如何通过间接方式采集目标服务数据 - 知乎
grafana 和 Prometheus 采集数据并展示 - 简书
内存彪高
创建大量对象导致的 垃圾回收跟不上速度 内存泄漏无法回收
jstat -gc pid 查看gc次数 时间
jmap -histo pid head -20 堆内存占用空间max的20个对象类型
逃逸分析
分析技术分析对象的动态作用域供其他优化措施提供依据
TLAB
为新对象分配内存空间时让每个Java应用线程能在使用自己专属的分配指针来分配空间Eden区默认Eden的1%减少同步开销