java
HashMap
实现方式:底层通过哈希表实现,就是要存储一个元素的时候,通过哈希函数算出一个哈希值,通过这个哈希值放到数组对应的位置,如果出现了哈希冲突,即两个元素的哈希值相同,HashMap采用了链地址法,数组的每个元素都是链表,如果不发生哈希冲突,把要存储的元素存储在value,next指向null,如果发生了哈希冲突,存储在链表的下一个结点的value,next指向链表的下一个结点
并发安全:多线程put发生哈希碰撞可能导致元素丢失,多线程put后可能导致get无限循环
HashTable
实现方式:put和get操作是synchronized修饰的,一个线程访问时,其他线程阻塞
concurrentHashMap
实现方式:value和next是用volatile修饰的,是分段锁,每个哈希地址都有一个锁
volatile
特点:可见性:某个线程修改了这个变量的值,其他线程读取到的值也会马上修改;有序性:禁止指令重排序
java高并发
synchronize:当前线程访问时,其他线程阻塞,竞争不激烈性能好
lock:当前线程阻塞时,其他线程阻塞,竞争激烈性能好
violate:可见性:某个线程修改了这个变量的值,其他线程读取到的值也会马上修改;有序性:禁止指令重排序
jvm内存区域
线程独占区:栈:函数中的临时变量,指向对象的地址;本地方法栈:c++的native方法;程序计数器:当前程序运行的位置
线程共享区:堆:对象;方法区:静态变量和方法,类加载器
jvm判断是否可以垃圾回收
引用计数器:给对象设置一个引用计数器,每当有一个地方引用它,数值+1,引用失效时,数值-1,数值为0时不可以被使用,缺点是不能解决循环引用问题
可达性分析算法:通过gcroot作为起始点向下搜索,走过的路径成为引用链,当一个对象到gcroot没有任何引用链相连的时候,可以回收,包括栈、本地方法栈、方法区中引用的对象
jvm的gc算法
标记清理:占满之后,要回收的对象先标记后清理,简单,会产生内存碎片
标记整理:清理之后,用存活的对象补上空位,不会产生内存碎片,开销大
复制:内存分为相等的两部分,只使用一部分,占满之后,要回收的对象做标记,没有标记的复制到另一部分,然后把刚才的部分清空,交替执行,开销小,不会产生内存碎片,内存利用率低
jvm的内存分代
新生代:eden区,survive0区,survive1区,1:1:8,eden区用复制算法复制到survive0区,然后把eden区和survive1区清空,survive0区和survive1区交替使用
老年代:存活超过6次的对象和eden区,survive区放不下的大对象
操作系统
进程间通信方式
管道,消息队列,贡献内存,信号,信号量,套接字
数据库
为什么数据库索引用b+数
因为和平衡二叉树相比,b+树高度更低,要访问某一个结点必须访问它的父结点,高度越低访问次数越少,查找越快
红黑树是特殊的二叉查找树,解决了二叉查找树在某些情况下变成链表的问题,b+树高度更低,访问次数少,查找快
和b树相比,b+树的非叶子结点只存储索引,范围查找需要返回父结点再往下查找,叶子结点存储索引和物理地址,而且所有的叶子结点通过链表相连,范围查找直接通过链表找到下一位,范围查找和排序速度快
其他
spring的特性
ioc控制反转:没有spring之前,需要程序员创建和管理对象,有了spring以后,spring容器可以生成和管理对象,相当于把对象的控制权交给了spring容器
di依赖注入:创建被调用者的实例的工作由spring容器完成,然后注入调用者
aop面向切面:将一些功能从业务逻辑里面独立出来,封装成一个切面,然后注入到具体业务逻辑中去
ioc的方法:构造器注入,setter方法注入,接口注入
依赖注入的方法:构造器注入,setter方法注入,接口注入
aop的方法:静态代理和动态代理
算法
最长不重复子串:力扣3