计算机基础知识补充

计算机网络

tcp粘包拆包

粘包

l在这里插入图片描述
两数据包合成一个数据包

拆包

在这里插入图片描述
一个数据包被拆成两部分,如上图的Packet1,Packet1的一部分还与Packet2发生的粘包

发生原因

  1. 应用程序写入的数据大于套接字缓冲区大小,这将会发生拆包。
    2.应用程序写入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘包。
    3.进行MSS(最大报文长度)大小的TCP分段,当TCP报文长度-TCP头部长度>MSS的时候将发生拆包。
    4.接收方法不及时读取套接字缓冲区数据,这将发生粘包。

解决办法

1、在数据包的首部记录数据包的长度
2、固定每个数据包的长度,不够的补零填充
3、在两个数据包之间设置边界,如添加特殊字符

https中的证书

SSL证书和我们日常用的身份证类似,是一个支持HTTPS网站的身份证明,SSL证书里面包含了网站的域名,证书有效期,证书的颁发机构以及用于加密传输密码的公钥等信息,由于公钥加密的密码只能被在申请证书时生成的私钥解密,因此浏览器在生成密码之前需要先核对当前访问的域名与证书上绑定的域名是否一致,同时还要对证书的颁发机构进行验证,如果验证失败浏览器会给出证书错误的提示。

ipv4和ipv6

ipv4 32位,ipv6 128位,ipv6 拥有更多的地址空间
在这里插入图片描述

SYN泛洪攻击

在TCP协议中被称为三次握手(Three-way Handshake)的连接过程中,如果一个用户向服务器发送了SYN报文,服务器又发出 SYN+ACK 应答报文后未收到客户端的 ACK 报文,这种情况下服务器端会再次发送SYN+ACK给客户端,并等待一段时间后丢弃这个未完成的连接,这段时间的长度称为SYN Timeout,一般来说这个时间是分钟的数量级。
在这里插入图片描述
SYN泛洪攻击指攻击者对服务器发送大量的tcp连接请求,但不对服务器发出的SYN+ACK 应答报文做出确认(如上图),服务器就会浪费资源维护大量的半连接状态,导致无法处理正常连接请求。

解决办法
1、缩短SYN timeout时间
2、设置SYN cookie
给每一个请求连接的IP地址分配一个cookie,如果短时间内连续受到某个IP的重复SYN文,认定是受到了攻击,以后从这个IP地址来的包会被丢弃
3、使用防火墙

ARP协议

arp广播是在局域网范围内的,如果两台主机不在同一个局域网,经路由器转发

dns域名解析过程

在这里插入图片描述

HTTP状态码

各类别常见状态码

  • 2xx (3种)

    200 OK:表示从客户端发送给服务器的请求被正常处理并返回;

    204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);

    206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。

  • 3xx (5种)

    301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;

    302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;

         301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
    

    303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;

        302与303的区别:后者明确表示客户端应当采用GET方式获取资源
    

    304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;

    307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);

  • 4xx (4种)

    400 Bad Request:表示请求报文中存在语法错误;

    401 Unauthorized:未经许可,需要通过HTTP认证;

    403 Forbidden:服务器拒绝该次访问(访问权限出现问题)

    404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;

  • 5xx (2种)

    500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;

    503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;

java

mybatis

工作原理

1、解析xml配置文件创建会话工厂SqlSessionFactory
2、从会话工厂中获得会话对象SqlSession(操作数据库的顶层接口)
3、SqlSession有个Excecutor对象,用来生成sql语句及维护缓存
4、通过jdbc执行sql语句
如果通过mapper接口的方式来操作数据库,则是通过动态代理实现的。

二级缓存

一级缓存作用范围为同一个SqlSession,二级缓存作用范围是同一个mapper(一般争对同一个表,用namespace区分),不同SqlSession中如果查询的是同一个mapper二级缓存也可以命中。

引用

  1. 软引用:内存不足时会被垃圾回收器回收掉。一般应用在缓存上。
  2. 弱引用:垃圾收集器扫描到就会回收,也可做缓存。
    此外ThreadLocal中key使用的是弱引用。(如下述代码)这是因为如果local引用为空,而作为local对象引用的key如果是强引用的话,那local对象就无法进行回收,会导致内存泄漏。如果为弱引用则会自动回收。
private static class A{
        private ThreadLocal<String> local = ThreadLocal.withInitial(() -> "in class A");

        public String get(){
            return local.get();
        }
        public void set(String str){
            local.set(str);
        }

    }
  1. **虚引用:**如同没有引用一样,一般配合引用队列跟踪对象的回收过程。

内存泄漏

长生命周期的对象持有短生命周期对象的引用,导致短生命周期对象不能被回收

  • 静态集合类:集合类静态的,长期存活,导致集合中的对象不能被回收
  • 内部类持有外部类:如果一个外部类的实例对象的方法返回了一个内部类的实例对象,这个内部类对象被长期引用了,即使那个外部类实例对象不再被使用,但由于内部类持有外部类的实例对象,这个外部类对象将不会被垃圾回收(静态内部类不持有外部类的引用,不存在该问题
  • 各种io连接或是资源请求,如果没有close释放,也会导致大量相关对象无法回收。

抽象类和接口

抽象类

  1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。

  2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

  3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。

  4. 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。

  5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

抽象类和接口的区别

  1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
    注:JDK 1.8 以后,接口里可以有静态方法和方法体了。

注:JDK 1.8 以后,接口允许包含具体实现的方法,该方法称为"默认方法",默认方法使用 default 关键字修饰。更多内容可参考 Java 8 默认方法。

注:JDK 1.9 以后,允许将方法定义为 private,使得某些复用的代码不会把方法暴露出去。更多内容可参考 Java 9 私有接口方法。

多态

表现为父类的引用指向子类的实例

如  : List<Integer> list=new ArrayList<>();

反射

在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法

  • 优点
    代码更加灵活,在各种框架中有大量应用
  • 缺点
    增加了安全问题

红黑树

性质1:每个节点要么是黑色,要么是红色。
性质2:根节点是黑色。
性质3:每个叶子节点(NIL)是黑色。
性质4:每个红色结点的两个子结点一定都是黑色。
性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。

红黑树相比于平衡二叉树(AVL)的优势:红黑树对于平衡要求没有AVL严格,所以查询效率低于avl,但红黑树在删除和增加节点时所作的开销相比与avl小许多。

ArrayList扩容

当新加入一个数据超过原先数据容量,进行扩容

  private void grow(int minCapacity) {
        // oldCapacity为旧容量,newCapacity为新容量
        int oldCapacity = elementData.length;
        //将oldCapacity 右移一位,其效果相当于oldCapacity /2,
        //我们知道位运算的速度远远快于整除运算,整句运算式的结果就是将新容量更新为旧容量的1.5倍,
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //然后检查新容量是否大于最小需要容量,若还是小于最小需要容量,那么就把最小需要容量当作数组的新容量,如果newCapacity溢出,肯定小于minCapacity,取minCapacity
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
       // 如果新容量大于 MAX_ARRAY_SIZE,进入(执行) `hugeCapacity()` 方法来比较 minCapacity 和 MAX_ARRAY_SIZE,
       //如果minCapacity大于最大容量,则新容量则为`Integer.MAX_VALUE`,否则,新容量大小则为 MAX_ARRAY_SIZE 即为 `Integer.MAX_VALUE - 8`。
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);

得到新容量后,要和MAX_ARRAY_SIZE进行比较,确保尽量不要超过MAX_ARRAY_SIZE,如果MAX_ARRAY_SIZE不够,新容量为Integer.MAX_VALUE

//比较minCapacity和 MAX_ARRAY_SIZE
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // minCapacity溢出抛异常
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

HashMap

给定的默认容量为 16(指数值),负载因子为 0.75。Map 在使用过程中不断的往里面存放数据,当实际大小达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容,而扩容这个过程涉及到 rehash、复制数据等操作,所以非常消耗性能。

hashmap扩容

hashmap会扩容至原先容量的两倍,对每个元素进行重hash,映射到新的数组位子,由于已两倍的方式进行扩容,重新计算hash有个巧妙的设计,即新的位置要么在原位置,要么在原长度+原位置的位置

数组长度(16):10000
两个key的hash值:1015->51010121->5
扩容:10000032)
两个key的hash值:1015->51010121->21=16+5

通过与原始数组长度做按位与运算判断最高位是否为1,为1:原长度+原位置的位置,否则:原位置

ConcurrentHashMap

多线程存在的问题

死锁和线程不安全

JDK1.6 之后的 synchronized 的优化

jdk1.6引入的偏向锁、轻量级锁、重量级锁,他们会随着竞争的激烈而逐渐升级。

  • 偏向锁
    一个线程获取某个对象的锁之后(修改对象头中的MarkWord值),以后该线程再访问锁住的同步块时不需要加锁、解锁操作。
  • 轻量级锁
    当两个线程竞争锁时偏向锁会升级为轻量级锁。轻量级锁的竞争通过CAS+自旋的方式进行。自旋是有时间限制的,如果长时间拿不到锁,则会升级为重量级锁。
  • 重量级锁
    重量级锁是传统的synchronized,未获取锁的线程就会挂起。
    在这里插入图片描述

ThreadLocal

被ThreadLocal修饰的变量在每个线程中都有一个副本。
每个Thread中都有一个ThreadLocalMap变量,副本就是保存在当前Thread的ThreadLocalMap中,某线程调用set改值时,先获取该线程的ThreadLocalMap,再通过ThreadLocalMap设置值。ThreadLocal则是作为ThreadLocalMap中的key来查询每个线程中副本值。

垃圾收集器

在这里插入图片描述
Serial
早期的垃圾收集器,标记复制,单线程,会暂停用户线程(有相应的老年代收集器,标记整理)
ParNew
Serial 的多线程版本,标记复制,多线程,会暂停用户线程
Parallel Scaveng
标记复制,多线程,注重吞吐量(高效利用cpu),自适应调节策略(有相应的老年代收集器,标记整理)
CMS
老年代,标记清除,注重用户体验,以降低用户线程停顿时间为目标,第一款真正意义上的并发收集器,实现了让垃圾收集线程与用户线程(基本上)同时工作。
在这里插入图片描述
缺点:

  • 吃cpu
  • 无法处理”浮动垃圾”(并发清除时产生的垃圾),如果预留的内存不足以分配这些新对象(浮动垃圾),会出现“并发失败”从而导致Full GC。
  • 它使用的回收算法-“标记-清除”算法会导致收集结束时会有大量空间碎片产生。

G1
面向全堆,是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足 GC 停顿时间要求的同时,还具备高吞吐量性能特征.
降低停顿时间是 G1 和 CMS 共同的关注点,但 G1 除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内。
G1将堆内存分为多个大小相等的区域(Region),以Region为单位进行收集
G1 收集器在后台维护了一个优先列表,每次根据允许的收集时间,优先选择回收价值最大的 Region(这也就是它的名字 Garbage-First 的由来) 。这种使用 Region 划分内存空间以及有优先级的区域回收方式,保证了 G1 收集器在有限时间内可以尽可能高的收集效率(把内存化整为零)。
G1从整体上来看是是标记整理,从局部来看(两个Region之间)是标记复制。

类加载过程

  1. 加载
    获取二进制字节流–》转化为方法区的运行时数据结构–》生成一个代表该类的Class对象
  2. 连接(验证、准备、解析)
  • 验证
    文件格式验证、元数据验证、字节码验证、符号引用验证,确保解析过程能正确执行
  • 准备
    为类变量(static修饰的变量)分配内存并设置类变量初始值(零值),并不执行程序赋值
 public static int value=123;

 准备阶段后value为0,并不是123
 但也有特殊情况
 如果类变量修饰为常量的话则会进行赋值
 
  public static final int value=123;

 此时value值为123.
  • 解析
    将常量池内的符号引用替换为直接引用的过程
  1. 初始化
    执行类的构造器()方法,该方法是由类中所有类变量的赋值动作和静态语句块(static{})合并而成,是真正开始执行类中编写的java程序代码

Reactor(反应堆)设计模式(NIO、IO多路复用)

Reactor模式是处理并发I/O常见的一种模式,用于同步I/O,其中心思想是将多个要处理的I/O请求注册到一个中心I/O多路复用器上(一个线程处理多个I/O请求),一旦有某个I/O请求的数据到来或是准备就绪,多路复用器将返回并将相应I/O请求分发到对应的处理器中。
在这里插入图片描述
在Java的NIO中,有个Selector(选择器)的概念,它就作为上述中的多路复用器。通过它,只需要一个线程便可以管理多个客户端连接。当客户端数据到了之后,才会为其服务。
在这里插入图片描述

comparator和comparable区别

comparator 是外部实现的比较器,重写int compare(Object o1, Object o2)方法,一般用于集合排序中
某个类实现comparable接口,表明该类是可比较的,可直接用于集合排序中,重写int compareTo(Object o)

spring 循环依赖

什么是循环依赖

bean A的属性含有bean B,bean B的属性含有bean A,或多个bean形成环形依赖

@Component
public class A {
  private B b;
  public void setB(B b) {
    this.b = b;
  }
}
@Component
public class B {
  private A a;
  public void setA(A a) {
    this.a = a;
  }
}

spring 解决方法

以上述代码为例,spring实例化对象A,要注入B,从而实例化B对象,要注入A,A此时存在,注入成功,(A目前属于半成品,属性B没有注入),B此时初始化成功(成品),然后对象A再注入B,A初始化成功(成品)。
在这里插入图片描述
简言之,两个池子:一个成品池子,一个半成品池子。能解决循环依赖的前提是:spring开启了allowCircularReferences,那么一个正在被创建的bean才会被放在半成品池子里。在注入bean,向容器获取bean的时候,优先向成品池子要,要不到,再去向半成品池子要。

上述例子采用的setter注入,当采用构造函数注入时,则无法解决循环依赖,因为实例化时就需要属性注入成功

对象一定分配在堆中吗

不一定,逃逸分析:如果确定每个对象一定在某个方法和线程范围内,该对象课可以直接分配在栈中(存在性能问题,一般不会开启)。

操作系统

进程和线程

进程:资源分配的基本单元
线程:独立调度的基本单元,一个进程包含多个线程,共享进程的资源

进程的创建、撤销、切换都比线程的开销大许多

大文件场景题

这类题一般因为数据量比较大,不能一次性读取到内存,所以需要采用分治的思想,将大文件分成多个小文件进行操作

1. 排序
每次读取小部分数据,排序后写入一个小文件,然后将这些小文件进行归并排序,整合到一个大文件中。(像两大文件中找出重复或不同的记录,可以先排序,然后使用双指针求解)
2. 去重
数据量太大,无法直接用hashset去重,可先使用hash映射将大文件的数据映射到不同的小文件里,相同的数据肯定在同一个文件,然后再用hashset去重
3.找top-K
先使用前k个节点构建堆结构,如果找最大(小)的k个值使用小(大)顶堆,新来的节点如果小(大)于根节点,直接忽略,大(小)于根节点则替换根节点然后重新调整堆结构。最后堆中剩余的节点即为最大(小)的k个值。

海量数据的搜索日志中,找出搜索频率最高的十个关键字,像这类题就需要先统计每个关键字的出现的频率,然后采用小顶堆做。
统计频率则通过hash映射的方法将大数据分成各个小文件进行统计(相同的数据肯定映射在同一个文件)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值