其他分享
首页 > 其他分享> > 随便学学

随便学学

作者:互联网

TCP的三次握手和四次挥手

TCP协议是7层网络协议中的传输层协议,负责数据的可靠传输。

在建立TCP连接时,需要通过三次握手来建立,过程是:

  1. 客户端向服务端发送SYN

  2. 服务端接收到SYN后,向客户端发送一个SYN_ACK

  3. 客户端收到SYN_ACK后,再给服务端发送一个ACK

在TCP连接时,需要通过四次挥手来断开,过程是:

  1. 客户端向服务端发送FIN
  2. 服务端接收到FIN后,向客户端发送ACK,表示我接收到了断开连接的请求,客户端你可以不发数据了,不过服务端这边可能还有数据正在处理
  3. 服务端处理完数据后向客户端发送FIN,表示客户端你可以断开连接了
  4. 客户端收到FIN后,向服务端发送ACK,表示我断开连接了

String、StringBuffer和StringBuilder的区别

  1. String是不可变的,如果尝试去修改,会生成一个新的字符串对象,StringBuffer和StringBuilder是可变的
  2. StringBuffer是先线程安全的,StringBuilder是线程不安全的,所以在单线程环境下使用StringBuilder效率会更高

ArrayList和LinkedList有哪些区别

  1. 首先,他们的底层数据结构不同,ArrayList底层是基于数组实现的,LinkedList底层是基于链表实现的
  2. 由于底层数据结构不同,他们所使用的场景也不同,ArrayList更适合随机查找,LinkedList更适合删除和添加
  3. 另外ArrayList和LinkedList都实现了List接口,但是LinkedList还额外实现了Deque接口,所以LinkedList还可以当作队列来使用

CopyOnWriteArrayList的底层原理是怎样的

  1. 首先CopyOnWriteArrayList内部也是用数组来实现的,在向CopyOnWriteArrayList添加元素时,会复制一个新的数组,写操作在新数组上进行,读操作在原数组上进行
  2. 写操作加锁,防止出现并发导致数据丢失的问题
  3. 写操作结束之后会把原数组指向新数组
  4. CopyOnWriteArrayList允许在写操作时来读取数据,大大提高了读的性能,因此适合读多写少的应用场景,但是CopyOnWriteArrayList会比较占内存,同时读到的数据可能不是最新的数据,所以不适合实时性要求很高的场景

HashMap的扩容机制原理

1.7版本

  1. 先生成新数组
  2. 遍历老数组中的每个位置上的链表上的每个元素
  3. 取每个元素的key,并基于新数组长度,计算出每个元素在新数组中的下标
  4. 将元素添加到新的数组中去
  5. 所有元素转移完了之后,将新数组赋值给HashMap对象的table属性

1.8版本

  1. 先生成新数组

  2. 遍历老数组中的每个位置上的链表或红黑树

  3. 如果是链表,则直接将链表中的每个元素重新计算下标,并添加到新数组中去

  4. 如果是红黑树,则先遍历红黑树,计算出红黑树中每个元素对应在新数组中的下标位置

    ​ a.统计每个下标位置的元素个数

    ​ b. 如果该位置下的元素个数超过了8,则生成一个新的红黑树,并将根节点添加到新数组的对应位置

    ​ c. 如果该位置下的元素个数没有超过8, 那么则生成一个新的链表,并将链表的头节点添加到新数组的对应位置

  5. 所有元素转移完了之后,将新数组赋值给HashMap对象的table属性

ConcurrentHashMap的扩容机制

1.7版本

  1. 1.7版本的ConcurrentHashMap是基于Segment分段实现的
  2. 每个Segment相当于一个小型的HashMap
  3. 每个Segment内部会进行扩容,和HashMap的扩容逻辑类似
  4. 先生成新的数组,然后转移元素到新数组中
  5. 扩容的判断也是每个Segment内部单独判断的,判断是否超过阈值

1.8版本

  1. 1.8版本的ConcurrentHashMap不再基于Segment实现
  2. 当某个线程进行put时,如果发现ConcurrentHashMap正在进行扩容那么该线程一起进行扩容
  3. 如果某个线程put时,发现没有正在进行扩容,则将key-value添加到ConcurrentHashMap中,然后判断是否超过阈值,超过了则进行扩容
  4. ConcurrentHashMap是支持多个线程同时进行扩容的
  5. 扩容之前也先生成一个新的数组
  6. 在转移元素时,先将原数组分组,将每组分给不同的线程来进行元素的转移,每个线程负责一组或多组的元素转移工作

java包装类型与基本类型的区别

  1. 包装类型可以为null,而基本类型不可以

  2. 包装类型可用于泛型,而基本类型不可以

  3. 基本类型比包装类型更高效,频繁的拆箱装箱会导致内存碎片过多,引发频繁的垃圾回收,影响性能。

  4. 两个包装类型的值可以相同,但不相等

    什么场景使用最优

    1. 缓存范围内使用速度最快。
    2. 对数据库的操作,需要对数值类型进行判空。

序列化和反序列化

概念

用途

使用

如果一个对象想要实现序列化必须实现下面两个接口之一:

New与反射创建对象的区别

  1. new出来的对象无法访问其中的私有属性,但是通过反射出来的对象我们可以通过setAccessible()方法来访问其中的私有属性
  2. 使用new创建一个对象实例的时候必须知道全类名,但是通过反射创建对象有时候不需要知道类名也可以,jdk动态代理

HashCode

HashCode的作用是获取哈希码,也称散列码,它实际上是返回一个int整数,这个哈希码的作用是确定该对象在哈希表中的索引位置

如何实现一个IOC容器

  1. 配置文件配置包扫描路径
  2. 递归包扫描获取.class文件
  3. 反射,确定需要交给IOC管理的类
  4. 对需要注入的类进行依赖注入

Java类加载器

JDK自带有三个类加载器:BootStrap Classloader、ExtClassLoader、AppClassLoader。

BootStrapClassLoader是ExtClassLoader的父类加载器,默认负责加载%JAVA_HOME%lib下的jar包和class文件

ExtClasssLoader是AppClassLoader的父类加载器,负责加载%JAVA_HOME%/lib/ext文件夹下的jar包和class类

AppClassLoader是自定义类加载器的父类,负责加载classpath下的类文件

继承ClassLoader实现自定义类加载器

双亲委托模型

好处:

GC如何判断对象可以被回收

引用计数法:可能会出现A引用了B,B又引用了A,这时候就算他们都不再使用了,但因为相互引用计数器=1永远无法被回收

GC Roots的对象有:

可达性算法中的不可达对象并不是立即死亡的,对象拥有一次自我拯救的机会。对象被系统宣告死亡至少要经历两次标记过程:第一次是经过可达性分析发现没有与GC Roots相连的引用链,第二次是在由虚拟机自动建立的Finalizer队列中判断是否需要执行Finalizer方法,执行后还不可达则进行回收,否则对象复活。

标签:学学,对象,元素,随便,引用,数组,客户端,加载
来源: https://www.cnblogs.com/gc5132/p/15149189.html