设计模式:
1.单例模式
最简单的单例,应用场景(spring bean默认实现singleton模式,其他模式是clone模式prototype,session,request,global session )
public class Single{
private static Single INS = null;
private Single(){
}
public static Single getIns(){
if(INS ==null) {
INS = new Single();
}
return INS;
}
}
这才是最简单的
public class Single{
private static Single INS = new Single();
private Single(){
}
public static Single getIns(){
return INS;
}
}
2.工厂模式(Simple factory 常见简单工厂)
public class SimpleFactory{
public static createA(){
return new A();
}
public static createB(){
return new B();
}
}
3.抽象工厂(Abstract Factory Spring beanFactory)
public class AbstaractFactory{
IA createA();
IB createB();
}
public class MFactory impl AbstaractFactory{
IA createA();
IB createB();
}
public class NFactory impl AbstaractFactory{
IA createA();
IB createB();
}
4.代理模式(dubbo 动态代理)
public class AObjAgent{
AObj obj = new AObj();
public String test(){
obj .test();
}
}
public class AObj{
public String test(){}
}
5.委托模式
近似等于代理模式
6.装饰者模式(继承添加新接口)
核心思想,继承拓展
简化版
public class A{
public void m(){}
}
public class B extend A{
public void n(){}
}
复杂版
public interface A{
public void m();
}
public class AClass{
public void m(){}
}
public interface B extend A{
public void n();
}
public class B extend AClass{
public void n(){}
}
7.责任链模式(过滤器,拦截器)
public interface Filter {
public void doFilter(FilterChain chain);
}
public class FilterChain {
private List<Filter> list = new ArrayList<>();
private int index = 0;
public FilterChain addFilter(Filter filter){
list.add(filter);
return this;
}
public void doFilter(){
if (index == list.size()) {return;}
this.list.get(index++).doFilter(this);
}
}
public class AFilter implements Filter{
@Override
public void doFilter(FilterChain chain){
System.out.println("A");
chain.doFilter();
}
}
public class BFilter implements Filter{
@Override
public void doFilter(FilterChain chain){
System.out.println("B");
chain.doFilter();
}
}
8.建造者模式(StringBuilder两种建造者)
复杂的逻辑封装到方法里,隐藏构建的过程
builder
public class A{}
public class builder{
public build(){
return new A();
}
}
- 桥接模式(WebApplicationContext 子类抽象类)
逻辑封装 子类传入
public interface AInterface{
public void aMethod();
}
public class A impl AInterface{
public void aMethod(){
}
}
public class B impl AInterface{
public void aMethod(){
}
}
public abstract class Handler {
protected AInterface a;
public Handler(AInterface a){
this.a = a;
}
protected abstract void runA();
}
public class TestHandler {
public Handler(int i ,AInterface a){
super(a);
}
protected void runA(){
a.aMethod();
}
}
10.适配器模式Adapter
新老业务做桥接
public class A{
public void aMethod(String arg1,String arg2);
public void aMethod();
}
public interface BInterface{
public void bMethod(String arg1);
}
public class BAdapter impl AInterface{
A a = new A();
public void aMethod(String arg1){
a.aMethod(arg1,null);
a.aMethod();
}
}
11.原型模式 clone已有的对象(spring bean)
public class A impl cloneable{
}
public class Main(){
private A a = new A();
public static void main(String[] args){
a=A.clone();
}
}
12.命令模式 封装指令
String test = "test";
if(test){
}
13.享元模式 线程池
降低内存损耗
线程池
14.观察者模式 事件-通知机制(两个实现,观察者模式)
事件模式
15.策略模式(一个接口多个实现,dubbo里面的mina框架,netty框架被封装成统一的接口,一个接口对应多个网络层实现)
16.模板模式(逻辑封装在父类里)
spring bean的实现
由compontentScan来扫描 spring默认xml中配置为< compontent-scan>标签标识包扫描路径
此时compontent/controller/service/Repository注解会被扫描到内存中
xml解析器(yml解析器或者其他解析器)解析bean定义,通过反射方式生成bean对象 springioc基本原理
@Bean注解方式 由开发者指定bean的定义,spring决定何时调用得到对象
rpc restful
rpc 代表 dubbo 将本地方法映射到远端 强调的主体是 动作
1.强制约定了对于接口的调用参数,接口定义
2.基于同种语言调用
restful 代表 spring cloud 体现的思想是 万物皆资源 http接口返回json为代表一系列接口
- 依托于api文档
2.不同语言之间可以互相调用系统解耦更方便
设计模式六大原则:
1.开闭原则(对修改关闭,对拓展开放)
2.依赖倒置原则(依赖于接口,而不依赖于具体实现)
3.单一职责原则(一个对象只实现一项功能)
4.里氏替换原则(所有父类能出现的地方,子类一定能出现,里氏替换原则是抽象的基石)
5.合成复用原则(对象之间的组合尽可能的采用组合的方式而不是继承)
6.最小依赖原则(一个类尽可能少的依赖其他对象,减少系统的耦合性)
gc:
可达性分析
1.引用计数
2.可达性分析
gc常用的算法有
1.标记清除算法(标记垃圾对象-清除,缺点易造成内存碎片,优点速度快)
2.标记整理算法(标记垃圾对象,将非垃圾对象向内存区一端移动,再将临界点之外的内存区清除,速度缓慢,但会有效减少内存碎片,容易形成连续的内存区)
3.复制算法(标记垃圾对象,将非垃圾对象标记复制到另一个内存区,将原内存区清除,缺点需要双倍内存区,优点当费垃圾对象较少时速度快)
4.分代收集算法(老年代新生代2:8,新生代采用标记清除算法,老年代采用标记整理算法,新生代到老年代晋级多次,当在新生代一定阈值存活之后采用复制算法)其中新生代称之为(Eden伊甸区(天堂死的快的么^^),取名字伊甸园,survivor老年代,又叫幸存区)
现在沿用的收集器
CMS收集器 +XX:+UseParNewGC(我特么最开始写+UseCMSGC 囧) 收集过程 初始标记,并发标记,重新标记,并发清除四个过程、
G1收集器: -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC 然后把 相较于CMS收集器的改进是:
1.内存分代不隔离
- 可预测停顿
java8 默认GC Parallel GC
java9 默认GC 是G1
Full GC 和 Minor GC
Minor GC Eden区GC
Full GC 清理整个内存空间
Major GC 老年代GC 一般来说 MinorGC 会出发FullGC
触发Full GC的条件
- System.gc()
- 老年代不足
- 永久带不足
- 新生代晋升老年代空间不足
- 堆中分配大对象,空间不足以分配
CMS收集器的收集过程
初始标记——>并发标记——>重新标记——>并发清除
即时编译JIT机制和编译优化
1.即时编译JIT,热点代码编译成本地平台机器码
算法两种:1采样定期采集栈顶方法 2. 定期统计(xx时间内打到xx次,过时减半)
两种
1。热点方法编译
- 回边方法编译(回边方法指的是:在代码执行流控制(跳转)的时候进行计数,达到一定阈值后编译整个方法)
ClassLoader
redis:
redis分布式锁的实现:setNx指令
redis的数据结构有:string hash list set sortedSet
CAP原则:
C 强一致性
A 可用性
P 分区容错性
定律:一个系统不可能三个同时满足,而只能同时达到三大原则中的两个
满足CA RDS mysql/sqlserver等关系型数据库
满足CP nosql为代表的 redis/mongodb/cache框架
满足AP 一些简单的数据库simple db
关系型数据库的原则为 CAP原则的变种 称之为ACID
其中 A 原子性
C 一致性
I 隔离性(独立性)
D 持久性
说说锁
乐观锁和悲观锁
悲观锁
悲观锁往往认为不加锁我完全没办法进行下一步操作
我所有数据随时有可能因为线程被挂起而会出现错误的数据
悲观锁的性能:在java中 线程的切换往往需要由用户态转换成系统太去完成线程的切换操作
其中完成了这样几部操作,保存线程A的CPU寄存器信息——>存储到CIP中——>从CIP中读取线程B的寄存器信息——>恢复执行线程B
在这其中 有可能耗费的时间比线程本身生命周期的时间还要长所以非常耗费性能
代表有synchronized,reentractLock 其中在java8中两者的性能耗费基本相同,但是 reentractLock中有一些高级特性
- 可以设置公平锁或者非公平锁
- 可以设置多个condition
在线程执行过程中,往往可能在线程挂起的下一瞬间,线程所竞争的资源就会被释放,而当线程下一次再被执行则需要好久,所以在java6以后进行线程的synchronized,reentractLock 和都会进行优化先进行自旋一段时间,当不能竞争到锁时再去进行线程挂起等待被唤醒
乐观锁
乐观锁在设计中认为随时可能资源被释放,而挂起线程是在浪费时间,因为当线程挂起的一瞬间锁就有可能被释放,所以乐观锁的设计是尽可能的不去挂起线程,而是假设程序在执行过程中都是没有冲突的,当冲突出现的时候尽可能的去尝试获取资源,直到得到资源典型代表就是CAS(Compare and Swap)
CAS
CAS在计算机中是一个CPU指令的应用(Compare and swap) 该指令是一个三操作数的指令 V A B即 内存地址 新值 旧值
其中在 x64和 x86 中是 comxchg执行来执行
在CAS中有一个bug 称之为ABA问题,即当A值被改变成B值之后又被改回A值 CAS会认为值没有改变但是实际上值已经被改变过了
解决方案是同时去改变两个值即给CAS的值是两个参数一个版本号一个目标值
公平锁和非公平锁
注意:这些划分只是单纯的从某个纬度去划分的,一个锁可能具备一个或多个特性
公平锁,当锁释放之后所有线程公平竞争没有优先级任何一个线程都有可能获得当前锁并执行,有的线程可能永远无法获取到锁
reentractLock 通过构造函数可以被构建成公平锁
非公平锁,当锁释放之后线程会按照一定优先级来竞争锁(时间,权重等)
synchronized就是一个非公平锁
reentractLock 默认也是非公平锁,可以通过boolean的构造函数来构造出公平锁
可重入锁和自旋锁
可重入锁,一个线程持有该锁之后,该线程下的子代码也持有该锁而无需再次获取,又叫递归锁
自旋锁,当一个代码获取到锁之后,其他代码访问该锁的时候不断尝试(循环)获取该锁而不是中断
读写锁
reentractReadWriteLock
读写锁允许多个线程同时读,但只允许同一个线程同时写
轻量锁和重量锁
是否会阻塞线程为标准(划重点)阻塞线程的叫重量级锁,不阻塞的叫轻量级锁
偏向锁
大多数情况下 锁不仅不存在线程竞争并且是由同一个线程多次获取,为了减小锁获取的代价
偏向锁的理解:
当一个线程被初始化的时候偏向锁是无状态的,当一个线程访问该对象的时候,检查偏向锁,将该对象的偏向锁的threadId改成自己的,当再次访问该对象的时候直接比对偏向锁的threadId如果是自己的则不用获取锁,如果不是自己的则唤醒持有该锁的线程,如果线程不存活,则直接将偏向锁记录的id改成自己的,如果线程存活,则让其继续执行完这一段代码,这时候偏向锁升级为轻量级锁,即有冲突但冲突程度很轻,这个时候如果第三个线程进来了,则认为该锁竞争程度很大,则将除了持有锁的其它线程全部阻塞,此时轻量级锁升级为重量级锁
Mark Word 当前对象状态
对象头信息:
偏向锁 地址