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