2024年java面试准备--网络基础篇(一)https://developer.aliyun.com/article/1393082
HTTP协议
1、HTTP协议1.0_1.1_2.0
HTTP1.0: 服务器处理完成后立即断开TCP连接(无连接),服务器不跟踪每个客户端也不记录过去的请求(无状态)
HTTP1.1:KeepAlived长连接避免了连接建立和释放的开销;通过Content-Length来判断当前请求数据是否已经全部接受(有状态)
HTTP2.0:引入二进制数据帧和流的概念,其中帧对数据进行顺序标识;因为有了序列,服务器可以并行的传输数据。
http1.0和http1.1的主要区别如下: 1、缓存处理:1.1添加更多的缓存控制策略(如:Entity tag,If-Match) 2、网络连接的优化:1.1支持断点续传 3、错误状态码的增多:1.1新增了24个错误状态响应码,丰富的错误码更加明确各个状态 4、Host头处理:支持Host头域,不在以IP为请求方标志 5、长连接:减少了建立和关闭连接的消耗和延迟。
http1.1和http2.0的主要区别: 1、新的传输格式:2.0使用二进制格式,1.0依然使用基于文本格式 2、多路复用:连接共享,不同的request可以使用同一个连接传输(最后根据每个request上的id号组合成正常的请求) 3、header压缩:由于1.X中header带有大量的信息,并且得重复传输,2.0使用encoder来减少需要传输的hearder大小 4、服务端推送:同google的SPDUY(1.0的一种升级)一样
2、HTTP与HTTPS之间的区别
HTTP与HTTPS之间的区别:
HTTP | HTTPS |
默认端口80 | HTTPS默认使用端口443 |
明文传输、数据未加密、安全性差 | 传输过程ssl加密、安全性较好 |
响应速度快、消耗资源少 | 响应速度较慢、消耗资源多、需要用到CA证书 |
HTTPS链接建立的过程:
1.首先客户端先给服务器发送一个请求
2.服务器发送一个SSL证书给客户端,内容包括:证书的发布机构、有效期、所有者、签名以及公钥
3.客户端对发来的公钥进行真伪校验,校验为真则使用公钥对对称加密算法以及对称密钥进行加密
4.服务器端使用私钥进行解密并使用对称密钥加密确认信息发送给客户端
5.随后客户端和服务端就使用对称密钥进行信息传输
对称加密算法:
双方持有相同的密钥,且加密速度快,典型对称加密算法:DES、AES
非对称加密算法:
密钥成对出现(私钥、公钥),私钥只有自己知道,不在网络中传输;而公钥可以公开。相比对称加密速度较慢,典型的非对称加密算法有:RSA、DSA
3、Get和Post请求区别
HTTP请求:
方法 | 描述 |
GET | 向特定资源发送请求,查询数据,并返回实体 |
POST | 向指定资源提交数据进行处理请求,可能会导致新的资源建立、已有资源修改 |
PUT | 向服务器上传新的内容 |
HEAD | 类似GET请求,返回的响应中没有具体的内容,用于获取报头 |
DELETE | 请求服务器删除指定标识的资源 |
OPTIONS | 可以用来向服务器发送请求来测试服务器的功能性 |
TRACE | 回显服务器收到的请求,用于测试或诊断 |
CONNECT | HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 |
get和Post区别:
GET | POST | |
可见性 | 数据在URL中对所有人可见 | 数据不会显示在URL中 |
安全性 | 与post相比,get的安全性较差,因为所 发送的数据是URL的一部分 |
安全,因为参数不会被保存在浏览器 历史或web服务器日志中 |
数据长度 | 受限制,最长2kb | 无限制 |
编码类型 | application/x-www-form-urlencoded | multipart/form-data |
缓存 | 能被缓存 | 不能被缓存 |
4、HTTP常见响应状态码
100:Continue --- 继续。客户端应继续其请求。
200:OK --- 请求成功。一般用于GET与POST请求。
301:Moved Permanently --- 永久重定向。
302:Found --- 暂时重定向。
400:Bad Request --- 客户端请求的语法错误,服务器无法理解。
403:Forbideen --- 服务器理解请求客户端的请求,但是拒绝执行此请求。
404:Not Found --- 服务器无法根据客户端的请求找到资源(网页)。
500:Internal Server Error --- 服务器内部错误,无法完成请求。
502:Bad Gateway --- 作为网关或者代理服务器尝试执行请求时,从远程服务器接收到了无效的响应。
5、重定向和转发区别
重定向:redirect:
地址栏发生变化
重定向可以访问其他站点(服务器)的资源
重定向是两次请求。不能使用request对象来共享数据
转发:forward:
转发地址栏路径不变
转发只能访问当前服务器下的资源
转发是一次请求,可以使用request对象共享数据
6、Cookie和Session区别。
Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但两者有所区别:
Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行欺骗,考虑到安全应当使用session。
Cookie ⼀般⽤来保存⽤户信息,Session 的主要作⽤就是通过服务端记录⽤户的状态
浏览器输入URL过程
过程: DNS解析、TCP连接、发送HTTP请求、服务器处理请求并返回HTTP报文、浏览器渲染、结束
过程 | 使用的协议 |
1、浏览器查找域名DNS的IP地址 DNS查找过程(浏览器缓存、路由器缓存、DNS缓存) |
DNS:获取域名对应的ip |
2、根据ip建立TCP连接 | TCP:与服务器建立连接 |
3、浏览器向服务器发送HTTP请求 | HTTP:发送请求 |
4、服务器响应HTTP响应 | HTTP |
5、浏览器进行渲染 |
操作系统基础
进程和线程的区别
进程: 是资源分配的最小单位,一个进程可以有多个线程,多个线程共享进程的堆和方法区资源,不共享栈、程序计数器
线程: 是任务调度和执行的最小单位,线程并行执行存在资源竞争和上下文切换的问题
协程: 是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。
1、进程间通信方式IPC
管道pipe:
亲缘关系使用匿名管道,非亲缘关系使用命名管道,管道遵循FIFO,半双工,数据只能单向通信;
信号:
信号是一种比较复杂的通信方式,用户调用kill命令将信号发送给其他进程。
消息队列:
消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点。
共享内存(share memory):
- 使得多个进程可以可以直接读写同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。
- 由于多个进程共享一段内存,因此需要依靠某种同步机制(如信号量)来达到进程间的同步及互斥。
信号量(Semaphores) :
信号量是⼀个计数器,⽤于多进程对共享数据的访问,这种通信⽅式主要⽤于解决与同步相关的问题并避免竞争条件。
套接字(Sockets) :
简单的说就是通信的两⽅的⼀种约定,⽤套接字中的相关函数来完成通信过程。
2、用户态和核心态
用户态: 只能受限的访问内存,运行所有的应用程序
核心态: 运行操作系统程序,cpu可以访问内存的所有数据,包括外围设备
为什么要有用户态和内核态:
由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络
用户态切换到内核态的3种方式:
a. 系统调用
主动调用,系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
b. 异常
当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,比如缺页异常,这时会触发切换内核态处理异常。
c. 外围设备的中断
当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会由用户态到内核态的切换。
3、操作系统的进程空间
栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。
堆区(heap)— 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。
静态区(static)—存放全局变量和静态变量的存储
代码区(text)—存放函数体的二进制代码。
线程共享堆区、静态区
操作系统内存管理
存管理方式: 页式管理、段式管理、段页式管理
分段管理:
将程序的地址空间划分为若干段(segment),如代码段,数据段,堆栈段;这样每个进程有一个二维地址空间,相互独立,互不干扰。段式管理的优点是:没有内碎片(因为段大小可变,改变段大小来消除内碎片)。但段换入换出时,会产生外碎片(比如4k的段换5k的段,会产生1k的外碎片)
分页管理:
在页式存储管理中,将程序的逻辑地址划分为固定大小的页(page),而物理内存划分为同样大小的页框,程序加载时,可以将任意一页放入内存中任意一个页框,这些页框不必连续,从而实现了离散分离。页式存储管理的优点是:没有外碎片(因为页的大小固定),但会产生内碎片(一个页可能填充不满)
段页式管理:
段⻚式管理机制结合了段式管理和⻚式管理的优点。简单来说段⻚式管理机制就是把主存先分成若⼲段,每个段⼜分成若⼲⻚,也就是说 段⻚式管理机制 中段与段之间以及段的内部的都是离散的
1、页面置换算法FIFO、LRU
置换算法: 先进先出FIFO、最近最久未使用LRU、最佳置换算法OPT
先进先出FIFO:
缺点:没有考虑到实际的页面使用频率,性能差、与通常页面使用的规则不符合,实际应用较少
最近最久未使用LRU:
原理:选择最近且最久未使用的页面进行淘汰
优点:考虑到了程序访问的时间局部性,有较好的性能,实际应用也比较多
缺点:没有合适的算法,只有适合的算法,lFU、random都可以
/** * @program: Java * @description: LRU最近最久未使用置换算法,通过LinkedHashMap实现 * @author: Mr.Li * @create: 2020-07-17 10:29 **/ public class LRUCache { private LinkedHashMap<Integer,Integer> cache; private int capacity; //容量大小 /** *初始化构造函数 * @param capacity */ public LRUCache(int capacity) { cache = new LinkedHashMap<>(capacity); this.capacity = capacity; } public int get(int key) { //缓存中不存在此key,直接返回 if(!cache.containsKey(key)) { return -1; } int res = cache.get(key); cache.remove(key); //先从链表中删除 cache.put(key,res); //再把该节点放到链表末尾处 return res; } public void put(int key,int value) { if(cache.containsKey(key)) { cache.remove(key); //已经存在,在当前链表移除 } if(capacity == cache.size()) { //cache已满,删除链表头位置 Set<Integer> keySet = cache.keySet(); Iterator<Integer> iterator = keySet.iterator(); cache.remove(iterator.next()); } cache.put(key,value); //插入到链表末尾 } }
/** * @program: Java * @description: LRU最近最久未使用置换算法,通过LinkedHashMap内部removeEldestEntry方法实现 * @author: Mr.Li * @create: 2020-07-17 10:59 **/ class LRUCache { private Map<Integer, Integer> map; private int capacity; /** *初始化构造函数 * @param capacity */ public LRUCache(int capacity) { this.capacity = capacity; map = new LinkedHashMap<Integer, Integer>(capacity, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > capacity; // 容量大于capacity 时就删除 } }; } public int get(int key) { //返回key对应的value值,若不存在,返回-1 return map.getOrDefault(key, -1); } public void put(int key, int value) { map.put(key, value); } }
最佳置换算法OPT:
原理:每次选择当前物理块中的页面在未来长时间不被访问的或未来不再使用的页面进行淘汰
优点:具有较好的性能,可以保证获得最低的缺页率
缺点:过于理想化,但是实际上无法实现(没办法预知未来的页面)
2、死锁条件、解决方式。
死锁是指两个或两个以上进程在执行过程中,因争夺资源而造成的下相互等待的现象;
死锁的条件:
互斥条件:进程对所分配到的资源不允许其他进程访问,若其他进程访问该资源,只能等待至占有该资源的进程释放该资源;
请求与保持条件:进程获得一定的资源后,又对其他资源发出请求,阻塞过程中不会释放自己已经占有的资源
非剥夺条件:进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用后自己释放
循环等待条件:系统中若干进程组成环路,环路中每个进程都在等待相邻进程占用的资源
解决方法: 破坏死锁的任意一条件
乐观锁,破坏资源互斥条件,CAS
资源一次性分配,从而剥夺请求和保持条件、tryLock
可剥夺资源:即当进程新的资源未得到满足时,释放已占有的资源,从而破坏不可剥夺的条件,数据库deadlock超时
资源有序分配法:系统给每类资源赋予一个序号,每个进程按编号递增的请求资源,从而破坏环路等待的条件,转账场景
面试题
构造方法
构造方法可以被重载,只有当类中没有显性声明任何构造方法时,才会有默认构造方法。
构造方法没有返回值,构造方法的作用是创建新对象。
初始化块
静态初始化块的优先级最高,会最先执行,在非静态初始化块之前执行。
静态初始化块会在类第一次被加载时最先执行,因此在 main 方法之前。
This
关键字 this
代表当前对象的引用。当前对象指的是调用类中的属性或方法的对象
关键字 this
不可以在静态方法中使用。静态方法不依赖于类的具体对象的引用
重写和重载的区别
重载指在同一个类中定义多个方法,这些方法名称相同,签名不同。
重写指在子类中的方法的名称和签名都和父类相同,使用override注解
Object类方法
toString 默认是个指针,一般需要重写
equals 比较对象是否相同,默认和==功能一致
hashCode 散列码,equals则hashCode相同,所以重写equals必须重写hashCode
finalize 用于垃圾回收之前做的遗嘱,默认空,子类需重写
clone 深拷贝,类需实现cloneable的接口
getClass 反射获取对象元数据,包括类名、方法、
notify、wait 用于线程通知和唤醒
基本数据类型和包装类
类型 | 缓存范围 |
Byte,Short,Integer,Long | [-128, 127] |
Character | [0, 127] |
Boolean | [false, true] |