导图社区 Java基础知识点总结
Java基础知识点总结,包含DB,design pattern,工厂模式,JVM,algorithm,thread等内容
编辑于2022-05-14 16:17:14Java基础知识点总结
DB
MySQL
存储引擎
MyISAM默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果执行大量的select,insert MyISAM比较适合。 如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况
MyISAM
InnoDB事务原理
MVCC多版本并发控制
B+树存储数据
支持节点间的横向搜索,不用每次都从树顶往下搜索 B+树的优势: 1.单一节点存储更多的元素,使得查询的IO次数更少。 2.所有查询都要查找到叶子节点,查询性能稳定。 3.所有叶子节点形成有序链表,便于范围查询。 https://blog.csdn.net/qq_26222859/article/details/80631121
事务隔离级别
https://www.cnblogs.com/catmelo/p/8878961.html
ACID
原子性:一个事务要么全部完成,要么失败 一致性:从一个状态转变到另一个状态,没有数据的中间状态 隔离性:为保证性能,破坏一致性 持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响 https://blog.csdn.net/dengjili/article/details/82468576
未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
读已提交(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
HBase/Mongo
DesignPattern
工厂模式
简单工厂
普通工厂
单例
观察者
责任链
装饰器
代理
JVM
GC
GC算法
复制
Serial/ParNew/ParallelScanvage
标记清除
SerialOld
标记整理
SerialOld/ParallelOld
GS组件
SerialNew SerialOld(FullGC默认收集器)
ParNew
一般配合CMS 响应时间优先
ParallelScanvage + ParallelOld
吞吐量优先,年轻代年老代都是并行收集
CMS
并发清理,不停止用户线程,提高相应时间
G1
不区分年轻代年老代,弹性垃圾回收
线程执行到达 SafePoint SafeRegion 开始FullGC
引用
可达性分析算法(JVM使用)
引用计数算法(难解决循环引用)
四种引用关系
强、软、弱(Guava)、幻
句柄池
Hotspot JVM 使用的是直接内存,为了更快的查找速度
类加载机制
双亲委派
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。 每一个层次的类加载器都是如此。因此,所有的加载请求最终都应该传送到顶层的启动类加载器中。 只有当父加载器反馈自己无法完成这个加载请求时(搜索范围中没有找到所需的类),子加载器才会尝试自己去加载。 https://www.jianshu.com/p/353c26c744df
双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。
OSGI
https://blog.csdn.net/vking_wang/article/details/12875619
问题:类加载器死锁或者在动态环境下的OutOfMemoryError问题
假如bundleE不存在,则bundleC就不会被解析成功,会有错误消息提示为何未能解析;而不是报错ClassNotFoundException或NoClassDefFoundError。
在标准Java类加载模型中,总是会在classpath那一长串列表中进行查找;而OSGi类加载器能立即知道去哪里找类
内存模型
堆
new 对象
栈
虚拟机栈(线程私有)
方法变量
方法递归调用过程,就是典型的进栈出栈的过程
本地方法栈(JVM native修饰的方法)
方法变量
方法递归调用过程,就是典型的进栈出栈的过程
程序计数器
如果线程正在执行的是Java 方法,则这个计数器记录的是正在执行的虚拟机字节码指令地址,用于线程切换后的方法继续执行
如果正在执行的是Native 方法,则这个计数器值为空(Undefined),因为native不编译成字节码
常量池、方法区、永久代
静态常量,静态类,字符串
常用指令
jstat
GC 情况
jmap
堆内存现状(年轻代,年老代)
找出大对象 -histo:live | head -n 10
jstack
线程堆栈(查看死锁)
JVMTI
ClassLoader层的加解密
Algorithm
二叉树
平衡二叉树
前后先序遍历
B+树
红黑树
https://www.cnblogs.com/skywang12345/p/3245399.html
排序
快速排序
归并排序
冒泡排序
二分查找
Thread
线程池
ThreadPoolExecutor
核心线程数,最大线程数,线程空闲等待时间,队列,线程生产工厂,Reject异常捕捉类
newFixedThreadPool
newSchedualThreadPool
newSingleThreadPool
newCacheThreadPool
ForkJoinPool
RecursiveTask Task1.fork() Task2.fork() 1/2.join()
工具包
内存栅栏
volatile
底层使用INTER MESI协议,保证高速缓存一致性,当一个变量写入时,使缓存中其他对这个变量值的引用副本立即失效。 当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
只能保证多线程间的可见性,多线程写还是有线程安全问题
可以使用 Thread.MemoryBarrier();自行操作栅栏
int a=1;//可能存在缓存cache_a int b=2;//可能存在缓存cache_b,并且a与b的写入顺序可任意优化 Thread.MemoryBarrier();//将a、b写入内存,写入过程:cache-->内存 int c=3;//a、b的写入顺序,不能在c写入内存之后 Console.Write(b)//这里的b此时如果造我的理解,它是从内存中读取,而不是cache_b,因为在调用MemoryBarrier时,cache_b已经失效 --------------------- 作者:见证大牛成长之路 来源:CSDN 原文:https://blog.csdn.net/shanyongxu/article/details/48053675 版权声明:本文为博主原创文章,转载请附上博文链接!
可重入锁
synchronized
尽量写在代码块上,不要在方法上 1、synchronized在对象A的普通方法B上,多线程调用A的B方法时,能起到加锁作用。如果多线程每个自己都new了一个对象,再去调用方法B,这时候加锁就不起作用了,因为这时候的synchronized作用域为this 2、synchronized在对象A的静态方法B上,多线程调用A的B方法时,能起到加锁作用,即使new一个对象,但是B方法是静态的,还是能起到加锁作用。 3、synchronized(Foo.class)获取的是类的monitor,所以与public synchronized static void some()修饰静态方法是等价的 synchronized(this)获取的是当前实例的monitor,所以与public synchronized void some()修饰实例方法是等价的
lock
lock/unlock实现锁
可获取锁持有状态,设置获取锁超时时间
lock与sync区别
1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现; 2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁; 3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断; 4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。 5)Lock可以提高多个线程进行读操作的效率。 在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。
可中断/可实现公平竞争
lock与sync选择
在一些内置锁无法满足需求的情况下,ReentrantLock可以作为一种高级工具。当需要一些高级功能时才应该使用ReentrantLock,这些功能包括:可定时的,可轮询的与可中断的锁获取操作,公平队列,以及非块结构的锁。否则,还是应该优先使用Synchronized
同步辅助类
以下都基于AQS https://www.cnblogs.com/dolphin0520/p/3920397.html
CountDownLatch
保证多线程执行完毕,不能重复使用
Cyclicbarrier
可重复使用的栅栏
Semaphore
5把钥匙,循环放钥匙,用完放回去,没有拿到钥匙则等着
Phaser
阶段器:switch case
protected boolean onAdvance(int phase, int registeredParties) { //在每个阶段执行完成后回调的方法 switch (phase) { case 0: return studentArrived(); case 1: return finishFirstExercise(); case 2: return finishSecondExercise(); case 3: return finishExam(); default: return true; } }
Atomic
AtomicInteger/Long/Boolean
线程间通信
阻塞队列
BlockingQueue
Exchanger
线层与进程
进程是资源分配的最小单位,线程是程序执行的最小单位。
线层
线程是程序执行时的最小单位,它是进程的一个执行流,是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。同样多线程也可以实现并发操作,每个请求分配一个线程来处理。
进程
进程是资源(CPU、内存等)分配的基本单位,它是程序执行时的一个实例。程序运行时系统就会创建一个进程,并为它分配资源,然后把该进程放入进程就绪队列,进程调度器选中它的时候就会为它分配CPU时间,程序开始真正运行。