Java笔记
2021-01-20 14:26:38 10 举报
AI智能生成
Java知识网络
作者其他创作
大纲/内容
集合
ArrayList
线程不安全
使用Vector或者Collections.synchronizedList()包装
底层数组
查询效率高,增删效率低
无参初始化默认容量为0,add时默认容量变为10
扩容机制:1.5左右
初始化仅初始化容量大小,因此使用set方法时会报下标越界异常
增删都需要复制
内存连续
Vector
线程安全(大量使用synchronized关键字)
效率低下
扩容机制:默认2倍
各方法单独加synchronized
多个线程对同一个对象进行不同操作是仍然会出现线程安全问题
HashTable
线程安全
效率较低
get与put都会加锁
键值均不可为null
默认容量11
扩容规则翻倍+1
ConcurrentHashMap
jdk1.7-
volatile
可见性
有序性
原子性
Segment 数组、HashEntry
引入Segment分段锁
继承ReentrantLock
线程安全
jdk1.8
CAS + synchronized
相对jdk1.7-进一步降低了锁的粒度
hashEntry变为Node,引入红黑树(默认大于8时转换)
HashMap
jdk1.7-
结构:数组+链表
头插法(在扩容时可能产生循环链表)
jdk1.8+
结构:数组+链表+红黑树
当链表长度大于8并且数组长度大于64时,才会转换为红黑树
尾插法
put与get方法未加锁,线程依然不安全
线程不安全
默认容量为16
指定容量初始化
取模运算:h & (length-1)
扰动算法
键值均可为null
LinkedList
计算机基础
计算机网络
TCP传输控制协议
UDP用户数据报协议
Http
Https
加解密算法
对称加密
DES、AES、3DES、DESX、Blowfish、RC4、RC5、RC6
非对称加密
RSA、DSA、ECC、DH
并发编程
锁
锁概念
互斥锁
加锁失败后,线程会释放 CPU ,给其他线程
自旋锁
加锁失败后,线程会忙等待,直到它拿到锁
读写锁
读锁
共享锁
写锁
独占锁
读优先锁
写优先锁
公平读写锁
悲观锁
乐观锁
锁实现
synchronized Jvm内置锁
优化:自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等
修饰实例方法
monitorenter,monitorexit
修饰静态方法
ACC_SYNCHRONIZED 关键字<br>
修饰代码块
锁升级
无锁
偏向锁
如果一个线程获得了锁,那么锁就进入偏向模式
轻量级锁
对绝大部分的锁,在整个同步周期内都不存在竞争
自旋锁
避免用户态与内核态的切换
重量级锁
可重入
不可中断性
锁消除
Java虚拟机在JIT编译时(可以简单理解为当某段代码即将第一次被执行时进行编译,又称即时编<br>译),通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁<br>
volatile
保证变量的可见性
提示JVM从主存中获取数据
防止指令重排序
性能高,只能作用于变量
内存屏障Memory Barrier<br>
ThreadLocal
将当前线程作为Key,为每一个线程维护专属与自己的值
有内存泄漏的风险
CAS
乐观锁的实现,产生ABA问题
解决:加版本号,时间戳
实现方式
继承Thread
实现Runnable<br>
实现Callable
Thread
状态
new<br>
RUNNING<br>
READY<br>
TERMINATED<br>
WAITING<br>
TIMED_WAITING
BLOCKED
AQS
特性
阻塞等待队列
共享/独占<br>
公平/非公平<br>
可重入<br>
允许中断<br>
维护一个volatile int state (32位)
ReentrantLock
相比synchronized,ReentrantLock增加了①等待可中断;②可实现公平锁;③可实现选择性通知(锁可以绑定多个条件)
基于AQS抽象队列同步器
独占
共享
Semaphore
Semaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目。
acquire
release
CountDownLatch
使一个线程等待其他线程执行完毕后再执行
通过计数器实现
计数器的初始值时线程的数量
countDown
await
JVM
JMM(Java内存模型)
八种同步操作:lock,unlock,read,load(载入),use,assign(赋值),store(存储),write<br>
本地方法栈
虚拟机栈
方法区
堆
新生代<br>
Eden空间[伊甸园]<br>
From Survivor空间<br>
To Survivor空间
Eden:From:To = 8:1:1
老年代
新生代:老年代 = 1:2<br>
程序计数器<br>
对象
对象头
普通对象
Mark work(32bits|64bits)+Klass point(32bits|64bits)
数组对象
Mark work(32bits|64bits)+Klass point(32bits|64bits)+array length(32bits|64bits)
实例数据
对其填充数据
空对象大小为8字节
HotSpot
JIT编译器
将热点代码编译成与本地平台相关的机器码
动态编译
热点代码
基于计数器的热点探测<br>
计数器超过一定阈值
方法调用计数器
回边计数器
循环体执行次数<br>
基于采样的热点探测
经常出现在栈顶的方法
解释器与编译器并存<br>
当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程<br>序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以<br>获取更高的执行效率。
当程序运行环境中内存资源限制较大(如部分嵌入式系统中),可以使用解释器执行节约内存,反<br>之可以使用编译执行来提升效率。
Server Compiler
更好的编译质量
Client Complier<br>
更高的编译速度
JIT优化
公共子表达式的消除<br>
int d = (c*b)*12+a+(a+b*c);->int d = E*12+a+(a+E);
方法内联
在使用JIT进行即时编译时,将方法调用直接使用方法体中的代码进行替换,这就是方法内联,减少了方<br>法调用过程中压栈与入栈的开销。同时为之后的一些优化手段提供条件。如果JVM监测到一些小方法被<br>频繁的执行,它会把方法的调用替换成方法体本身。<br>
逃逸分析
通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上
从jdk 1.7开始已经默认开始逃逸分析
-XX:+DoEscapeAnalysis : 表示开启逃逸分析<br>-XX:-DoEscapeAnalysis : 表示关闭逃逸分析
标量替换
在JIT阶段,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过JIT优化,就会把这个对象<br>拆解成若干个其中包含的若干个成员变量来代替。
同步锁消除
基于逃逸分析,当加锁的变量不会发生逃逸,是线程私有的完全没有必要加锁。 在JIT编译时期就<br>可以将同步锁去掉,以减少加锁与解锁造成的资源开销。
类加载机制
加载过程<br>
加载<br>
验证
准备<br>
解析
初始化
使用卸载
双亲委派原则
避免重复加载
破坏双亲委派原则
如Jdbc
Java8新特性
Lambda
能够使用Lambda的依据是必须有相应的函数接口
与匿名内部类不同
编译只生成一个class文件
lambda表达式被封装成主类的私有方法
this指向主类,而在匿名内部类指向匿名内部类
java.util.function
0 条评论
下一页