ConcurrentHashMap 为什么 key 和 value 不能为 null?
ConcurrentHashMap
的 key 和 value 不能为 null 主要是为了避免二义性。null 是一个特殊的值,表示没有对象或没有引用。如果你用 null 作为键,那么你就无法区分这个键是否存在于 中,还是根本没有这个键。同样,如果你用 null 作为值,那么你就无法区分这个值是否是真正存储在 中的,还是因为找不到对应的键而返回的。
进程与线程
进程是程序的一次执行流程,也是资源分配的最小单位,同一时刻的进程数不能超过核心数,进程可以看做是一个程序的实例,而线程是进程中的一个执行单元,多个线程共享同一个进程内的资源,是操作系统能够进行资源调度的最小单位,但也因此出现一些资源竞争问题或者是死锁问题
Run方法和Start方法
-
run方法是线程的执行体,里面包含了线程所要执行的逻辑代码,会在当前线程上下文中进行切换,并且不会创建新的线程
-
start方法会将一个线程置于就绪状态,并且为该线程分配一些系统资源
wait和sleep的区别
两者的作用都是让线程从运行态进入阻塞态
-
wait是Object类下的方法,sleep是Thread类中的static方法
-
sleep属于Time_Waiting状态,结束休眠后会自动唤醒,wait方法属于Waiting状态,需要手动唤醒
-
sleep在持有锁时执行,且不会释放锁资源,wait方法在执行后会释放锁资源
-
wait方法必须在持有锁时执行,wait方法会将持有锁的线程封装成node扔到waitSet中,这个操作需要调用ObjectMoniter对象的方法,如果没有持有synchronized锁的话就无法操作对象
new对象的过程
-
判断:检测对象是否被加载,链接和初始化,如果没有会进行类加载,生成相应的class对象
-
分配空间:计算对象占用空间的大小,在堆内存中开辟一块空间,分配空间主要有两种方式:1.指针碰撞(内存规整),2.空闲列表法:在未被占用的内存中选择一块
-
分配初值:设置默认值
-
执行init方法:初始化成员变量,执行实例代码块,调用构造方法,并把堆内对象的首地址赋值给引用变量。
负载均衡算法
-
轮询法:按照请求顺序分配服务器
-
随机法:随即调用后端服务器
-
源地址哈希法:将客户端的IP地址进行哈希计算得到的结构跟服务器列表长度进行取模
-
加权轮询法:给配置高,负载低的机器更高的权重,让其处理更多的请求
接口幂等性
同一个接口,多次发出同一个请求,必须保持操作只执行一次
为什么出现? 1. 网络波动2. 页面重复刷新 3.多次提交按钮
幂等性的确保:
-
token机制,提交后会验证是否token重复
-
添加唯一标识符
-
乐观锁机制,每次都会携带版本号,适用于修改操作
new String("abc")和String a = "abc"的区别
-
new String方法不管字符串常量池中有没有这个字符串对象都会在堆中新创建对象
-
String="abc"的方式会先去字符串常量池中查找,如果有的话会直接进行赋值操作,没有才会新创建对象
HashMap添加和扩容机制
-
添加
在jdk1,8之后,我们采用的是数组+链表+红黑树的策略,能够有效避免在1.7中出现遍历循环链表对的情况,我们每次添加一个键值对时,计算键的hash值,将该值的高16位和低16位进行异或运算,得到的值在与数组长度减一进行按位与操作,如果该位置有元素则发生hash冲突,采用链式存储法。
-
扩容
初始化数组长度为16,当我们的数组内元素到达临界值(负载因子*数组长度)会自动触发扩容机制,扩容长度为2倍原数组的长度
http和https
-
http是明文传输,而https是具有ssl加密的传输协议
-
http是无状态的
-
http的默认端口是80,https默认端口是443