TCP的三次握手说一下?为什么是三次握手?为什么是四次挥手?
三次握手四次挥手
三次握手:
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
只有经过三次握手才能确认双发的收发功能都正常,缺一不可:
1、第一次握手(客户端发送 SYN 报文给服务器,服务器接收该报文):客户端什么都不能确认;服务器确认了对方发送正常,自己接收正常 2、第二次握手(服务器响应 SYN 报文给客户端,客户端接收该报文): 客户端确认了:自己发送、接收正常,对方发送、接收正常;
服务器确认了:对方发送正常,自己接收正常
3、第三次握手(客户端发送 ACK 报文给服务器): 客户端确认了:自己发送、接收正常,对方发送、接收正常; 服务器确认了:自己发送、接收正常,对方发送、接收正常
四次挥手
为什么要四次挥手? 由于 TCP 的半关闭(half-close)特性,TCP 提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。
任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。
通俗的来说,两次握手就可以释放一端到另一端的 TCP 连接,完全释放连接一共需要四次握手。
举个例子:A 和 B 打电话,通话即将结束后,A 说 “我没啥要说的了”,B 回答 “我知道了”,于是 A 向 B 的连接释放了。但是 B 可能还会有要说的话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,于是 B 向 A 的连接释放了,这样整个通话就结束了。
JAVA异常机制
Throwable是所有错误与异常的超类,包含两个子类:错误与异常。 错误指程序中无法处理的错误,比如JVM出现问题、栈溢出、内存不足等,异常是指程序能够处理的问题,如下标越界、空指针异常等。
异常关键字
1、try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。 2、catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。 3、finally – finally语句块总是会被执行。它主要用于回收在try块里打开的物力资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。 throw – 用于抛出异常。 throws – 用在方法签名中,用于声明该方法可能抛出的异常。
常见的异常
异常捕获处理的方法通常有:
try-catch try-catch-finally try-finally try-with-resource
结构化编程语言
结构化编程 限制了goto语句
volatile关键字
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
原子性
只有语句1是原子操作
synchronized和Lock
Java内存模型只保证了基本读取和赋值是原子性操作,如果要实现更大范围操作的原子性,可以通过synchronized和Lock来实现。由于synchronized和Lock能够保证任一时刻只有一个线程执行该代码块,那么自然就不存在原子性问题了,从而保证了原子性。
可见性
对于可见性,Java提供了volatile关键字来保证可见性。 当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。 而普通的共享变量不能保证可见性,因为普通共享变量被修改之后,什么时候被写入主存是不确定的,当其他线程去读取时,此时内存中可能还是原来的旧值,因此无法保证可见性。 另外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。
有序性
在Java内存模型中,允许编译器和处理器对指令进行重排序,但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。
在Java里面,可以通过volatile关键字来保证一定的“有序性”(具体原理在下一节讲述)。另外可以通过synchronized和Lock来保证有序性,很显然,synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。
JVM内存模型
线程私有:本地方法栈、栈、程序计数器、 全局共享:方法区(存放static静态变量等)、堆(存对象)
GC机制
用来清理“堆” GCRoot机制,判断哪些类需要被删除。 1、最简单的思路:对不在GCRoot上的对象进行标记,然后把标记的类删掉,【问题:产生内存碎片】 2、改进:每一次清理后,进行整理【问题:代价大,需要不断前移】 3、复制算法:需要两倍内存 4、实际算法:Young区 Old区
常用GC:G1、ParNE、 CMS
|