某Java大佬在地表最强Java企业(阿里)面试总结

面试题真的是博大精深,也通过这个面试题学到了很多东西,很多笔者也不是很懂,如有描述错误的地方还望大佬赐教,
每一次面试都可能问到相同的问题,一面问到,二三面还可能会问到,笔者认为这一点是整理这篇面试题收获最大的一点。

目录:

一面

1.1、HashMap和Hashtable的区别
1.2、实现一个保证迭代顺序的HashMap
1.3、 说一说排序算法,稳定性,复杂度
1.4、 说一说GC
1.5、 可以保证的实习时长
1.6、 职业规划

二面

2.1、 自我介绍。
2.2、 JVM如何加载一个类的过程,双亲委派模型中有哪些方法br> 2.3、 HashMap如何实现的br> 2.4、 HashMap和Concurrent HashMap区别, Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全br> 2.5、 HashMap和HashTable 区别,HashTable线程安全吗br> 2.6、 进程间通信有哪几种方式br> 2.7、 JVM分为哪些区,每一个区干吗的br> 2.8、 JVM如何GC,新生代,老年代,持久代,都存储哪些东西br> 2.9、 GC用的引用可达性分析算法中,哪些对象可作为GC Roots对象br> 2.10、 快速排序,过程,复杂度br> 2.11、 什么是二叉平衡树,如何插入节点,删除节点,说出关键步骤。
2.12、 TCP如何保证可靠传输次握手过程br> 2.13、 TCP和UDP区别br> 2.14、 滑动窗口算法br> 2.15、 Linux下如何进行进程调度的br> 2.16、 Linux下你常用的命令有哪些br> 2.17、 操作系统什么情况下会死锁br> 2.18、 常用的hash算法有哪些br> 2.19、 什么是一致性哈希br> 2.20、 如何理解分布式锁br> 2.21、 数据库中的范式有哪些br> 2.22、 数据库中的索引的结构么情况下适合建索引br> 2.23、 Java中的NIO,BIO,AIO分别是什么br> 2.24、 用什么工具调试程序Console,用过吗br> 2.25、 现在JVM中有一个线程挂起了,如何用工具查出原因br> 2.26、 线程同步与阻塞的关系步一定阻塞吗塞一定同步吗br> 2.27、 同步和异步有什么区别br> 2.28、 线程池用过吗br> 2.29、 如何创建单例模式了双重检查,他说不是线程安全的。如何高效的创建一个线程安全的单例br> 2.30、 concurrent包下面,都用过什么br> 2.31、 常用的数据库有哪些edis用过吗br> 2.32、 了解hadoop吗说hadoop的组件有哪些下mapreduce编程模型。
2.33、 你知道的开源协议有哪些br> 2.34、 你知道的开源软件有哪些br> 2.35、 你最近在看的书有哪些br> 2.36、 你有什么问题要问我吗br> 2.37、 了解哪些设计模式说都用过哪些设计模式
2.38、 如何判断一个单链表是否有环br> 2.39、 操作系统如何进行分页调度br> 2.40、 匿名内部类是什么何访问在其外面定义的变量/p>

三面

3.1、 自我介绍,做过什么项目。
3.2、java虚拟机的区域如何划分,
3.3、 双亲委派模型中,从顶层到底层,都是哪些类加载器,分别加载哪些类br> 3.4、 有没有可能父类加载器和子类加载器,加载同一个类果加载同一个类,该使用哪一个类br> 3.5、 HashMap的结构,get(),put()是如何实现的br> 3.6、 ConcurrentHashMap的get(),put(),又是如何实现的oncurrentHashMap有哪些问题ConcurrentHashMap的锁是读锁还是写锁br> 3.7、 sleep()和wait()分别是哪个类的方法,有什么区别ynchronized底层如何实现的在代码块和方法上有什么区别br> 3.8、 什么是线程池果让你设计一个动态大小的线程池,如何设计,应该有哪些方法br> 3.9、 什么是死锁VM线程死锁,你该如何判断是因为什么果用VisualVM,dump线程信息出来,会有哪些信息br> 3.10、 查看jvm虚拟机里面堆、线程的信息,你用过什么命令br> 3.11、 垃圾回收算法有哪些MS知道吗何工作的br> 3.12、 数据库中什么是事务务的隔离级别务的四个特性么是脏读,幻读,不可重复读br> 3.13、 数据库索引的结构有哪些介绍B+树的结构。
3.14、 数据库中的分页查询语句怎么写br> 3.15、 什么是一致性哈希来解决什么问题br> 3.16、 Redis的存储结构,或者说如何工作的,与mysql的区别哪些数据类型br> 3.17、 项目中用到redis,为什么选用redis,了解其他NoSQL数据库吗你的项目中是如何运用redis的ey是什么,value是什么br> 3.18、 归并排序的过程间复杂度间复杂度平常用什么排序速排序。说说在那些场景下适用,哪些场景下不适用。
3.19、 Solr是如何工作的/p>

一面

1.1、HashMap和Hashtable的区别

继承:
Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。

锁:
Hashtable 中的方法是Synchronize的,而HashMap中的方法在缺省情况下是非Synchronize的。

方法:
HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因为contains方法容易让人引起误解。
Hashtable则保留了contains,containsValue和containsKey三个方法,其中contains和containsValue功能相同。

是否可以为null:
Hashtable中,key和value都不允许出现null值。
HashMap中,null可以作为键,这样的键只有一个。
Hashtable中有类似put(null,null)的操作,编译同样可以通过,因为key和value都是Object类型,但运行时会抛出NullPointerException异常,这是JDK的规范规定的。
Tips:
当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

遍历:
Hashtable、HashMap都使用了 Iterator。但是,Hashtable还使用了Enumeration的方式 。
计算Hash值:
HashTable直接使用对象的hashCode。
HashMap的Hash值:(key == null) 0 : (h = key.hashCode()) ^ (h >>> 16);
容量:
HashTable在不指定容量的情况下的默认容量为11,而HashMap为16,
Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。
Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。

1.2、实现一个保证迭代顺序的HashMap

使用HashMap的一个子类LinkedHashMap(顺序遍历的HashMap)进行研究

放入方法中:
重写了最关键的Node newNode(int hash, K key, V value, Node next)方法,该方法首先创建一个HashMap.Node的子类LinkedHashMap.Entry,它比Node多了两个指针Entry before, after;//用于保存前后两个节点的信息。

Tips:
LinkedHashMap拥有两个瞬时的属性

遍历:
使用迭代器进行遍历,继承于 抽象类。该迭代器拥有两个Entry的指针和,并结合Entry中的和指针,实现了LinkedHashMap中元素的顺序遍历

LinkedHashIterator的方法使用了,使得iterator的遍历按照放入顺序进行的。

取值方法:
LinkedHashMap重写了Map接口的V get(Object key)方法,该方法分两个步骤:

  1. 调用父类HashMap的getNode(hash(key), key)方法,获取value;
  2. 如果accessOrder(访问后重排序)为true(默认为false),那么移动所访问的元素到表尾,并修改head和tail的值。

1.3、 说一说排序算法,稳定性,复杂度

某Java大佬在地表最强Java企业(阿里)面试总结
这个东西还是面试前把每个排序算法都看一看比较好

1.4、 说一说GC

是Java虚拟机进行垃圾回收的主要场所,其次要场所是。
在堆中进行垃圾回收分为新生代和老生代;将新生代分成了(这里的独立区域只是一个相对的概念,并不是说分成三个区域以后就不再互相联合工作了),
分别为:Eden区、From Survivor区以及To Survivor,而Eden区分配的内存较大,其他两个区较小,每次使用Eden和其中一块Survivor。

在进行垃圾回收时,将Eden和Survivor中还存活着的对象进行一次性地复制到另一块Survivor空间上,直到其两个区域中对象被回收完成,
当Survivor空间不够用时,需要依赖其他老年代的内存进行分配担保。当另外一块Survivor中没有足够的空间存放上一次新生代收集下来的存活对象时,这些对象将直接通过分配担保机制进入老生代,大对象和长期存活的对象也会直接进入老年代。
如果老生代的空间也被占满,当来自新生代的对象再次请求进入老生代时就会报OutOfMemory异常。

大多数情况下,对象在新生代Eden区中分配,当Eden区没有足够空间进行分配时,虚拟机将发起一次Minor GC;
同理,当老年代中没有足够的内存空间来存放对象时,虚拟机会发起一次Major GC/Full GC。只要老年代的连续空间大于新生代对象总大小或者历次晋升的平均大小就会进行Minor GC,否则将进行Full CG。

虚拟机通过对象年龄计数器来判断存放在哪:
如果对象在Eden出生并经过一次Minor GC后仍然存活,并且能被Survivor容纳的话,将被移动到Survivor空间中,并将该对象的年龄设为1。
对象每在Survivor中熬过一次Minor GC,年龄就增加1岁,当他的年龄增加到最大值15(MaxTenuringThreshold)时,就将会被晋升到老年代中。
如果在Survivor空间中所有相同年龄的对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄。

Jdk8开始废弃永久代:
This is part of the JRockit and Hotspot convergence effort. JRockit customers do not need to configure the permanent generation (since JRockit does not have a permanent generation) and are accustomed to not configuring the permanent generation.
(移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代,不需要配置永久代。)
由于永久代内存经常不够用或发生内存泄露,爆出异常java.lang.OutOfMemoryError: PermGen
字符串存在永久代中,容易出现性能问题和内存溢出。
类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
永久代会为GC带来不必要的复杂度,而且回收效率偏低。

1.5、 可以保证的实习时长

一般都是半年到一年,(太少的话,刚教会了你,你就可能走了,太多的话也不现实)
还有可能问到什么时候去上班,建议的话,就是下个月,或者两周后,今天面试明天上班,肯定准备的不充分。(问这个的话,大多都是有个项目什么的着急要人,然后面试官用你应付,)

1.6、 职业规划

其实这个问题不只是回答面试官,更是回答自己,为什么做,想怎么做……

说明自己对岗位的理解和从事这份工作的原因。
说明自己愿意为这份工作付出努力。
说明自己长远的目标和规划。

下面以产品经理为例子回答:
互联网行业是一个高速发展的行业,同时也有大量创新和尝试的机会(阐述自己看好行业)。
而产品经理则是互联网企业的核心岗位之一,产品经理负责用户需求分析、竞品分析、产品设计和上下层需求的沟通,需要超强的逻辑思考和分析能力、用户洞察能力和沟通协作能力。(阐述自己对岗位的理解)。
而我毕业于XXX大学,在大学里曾参加XXX产品设计比赛,拿下了XXX的成绩,个人非常擅长思考和分析问题,同时能处理好和团队成员的沟通协作…(阐述自己适合这个工作)。

我认为自己非常适合这个岗位,为此,我也愿意付出努力。
在过去,我曾阅读过XXX本产品书籍,自己设计过3款产品的原型,有一款在自己的努力下成功上线,并通过持续获取用户反馈,收获了XXX万的用户。(表达自己过去的努力)
入职以后,我希望能从助理开始,系统学习产品的基本功,在一年的时间里面,成功掌握主流的产品设计方法论(表达自己愿意付出的努力)。
我知道,优秀的产品经理不仅仅需要掌握产品设计的方法,还需要XXXX。
我会努力培养自己的业务思维,站在全局业务的角度去思考和解决问题,为团队做好表率…(表达自己大致的努力方向)。

每个产品经理都有自己的目标,我也一样。
我希望在我的努力之下,在两年以后,能够独挡一面,负责好一个版块的功能;
在三到五年左右,可以负责好一个产品的规划、设计和优化;
在未来的五到八年,可以做好一个产品的全局规划、团队管理等等…

二面

2.1、 自我介绍。

自我介绍在三到五分钟最好
一两句话概括自己名字学校什么的,主学的什么,对什么有研究,了解什么(切忌:尽量别说“精通”),然后说一下以前做过的项目(具体说一些自己做的有技术的),或者什么别的奖项,然后谈一下自己对公司的了解以及对未来的规划,等等。(百度有很多,随便搜搜)

2.2、 JVM如何加载一个类的过程,双亲委派模型中有哪些方法/h2>

类加载过程:
加载
(通过一个类的全限定名获取定义此类的二进制字节流,将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构,在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区域数据的访问入口)、
验证
(验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害,如果验证失败,就会抛出一个java.lang.VerifyError异常或其子类异常。
1.文件格式验证:
验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。
2.元数据验证:
是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。
3.字节码验证:
主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。
4.符号引用验证:
符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。)、
准备
(准备阶段为(static)变量(不包括类的实例)分配内存并设置类变量的初始化,此初始化并不是赋值static int num =1,这时得num为0,并不是1)、
解析
(解析过程是将常量池内的符号引用替换成直接引用(类或接口的解析、字段解析、方法解析、接口方法解析。))、
初始化
(这里才是赋值阶段)
使用过程:新线程—程序计数器—-jvm栈执行(对象引用)—–堆内存(直接引用)—-方法区。
卸载靠GC

双亲委派模型中方法:
双亲委派是指如果一个类收到了类加载的请求,不会自己先尝试加载,先找父类加载器去完成。当顶层启动类加载器表示无法加载这个类的时候,子类才会尝试自己去加载。当回到最开的发起者加载器还无法加载时,并不会向下找,而是抛出ClassNotFound异常。

方法:启动(Bootstrap)类加载器,标准扩展(Extension)类加载器,应用程序类加载器(Application ),上下文(Custom)类加载器。意义是防止内存中出现多份同样的字节码 。

1)启动类加载器(Bootstrap ClassLoader):
负责加载JAVA_HOMElib目录中并且能被虚拟机识别的类库到JVM内存中,如果名称不符合的类库即使放在lib目录中也不会被加载。该类加载器无法被Java程序直接引用。
2)扩展类加载器(Extension ClassLoader):
按《深入理解java虚拟机》这本书上所说,该加载器主要是负责加载JAVA_HOMElibext目录中的类库,但是貌似在JDK的安装目录下,没看到该指定的目录。该加载器可以被开发者直接使用。
3)应用程序类加载器(Application ClassLoader):
该类加载器也称为系统类加载器,它负责加载用户类路径(Classpath)上所指定的类库,开发者可以直接使用该类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

2.3、 HashMap如何实现的/h2>

关于HashMap还是看一下这一篇比较好

HashMap的底层是数组+链表,(很多人应该都知道了)

JDK1.7的是
首先是一个数组,然后数组的类型是链表
元素是
JDK1.8的是
首先是一个数组,然后数组的类型是链表

在链表的元素大于8的时候,会变成红黑树
(当链表长度大于8并且数组长度大于64时,才会转换为红黑树。
如果链表长度大于8,但是数组长度小于64时,还是会进行扩容操作,不会转换为红黑树。因为数组的长度较小,应该尽量避开红黑树。因为红黑树需要进行左旋,右旋,变色操作来保持平衡,
所以当数组长度小于64,使用数组加链表比使用红黑树查询速度要更快、效率要更高。 )

在红黑树的元素小于6的时候会变成链表
(这里需要注意,不是元素小于6的时候一定会变成链表,只有resize的时候才会根据UNTREEIFY_THRESHOLD 进行转换,同样也不是到8的时候就变成红黑树(不是等到扩容的时候) 链表与红黑树的转换详情)
元素进行

2.4、 HashMap和Concurrent HashMap区别, Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全/h2>

关于HashMap还是看一下这一篇比较好

使用ConcurrentHashMap(线程安全),
JDK1.7的是分段数组,有加速一小段保证并发
JDK1.8 是和HashMap一样了,

(JVM在1.6对Synchronize的优化很好)

CAS通俗易懂,比较并替换
(CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做)
(无锁化的修改值的操作,他可以大大降低锁代理的性能消耗。这个算法的基本思想就是不断地去比较当前内存中的变量值与你指定的 一个变量值是否相等,如果相等,则接受你指定的修改的值,否则拒绝你的操作。因为当前线程中的值已经不是最新的值,你的修改很可能会覆盖掉其他线程修改的结果。这一点与乐观锁,SVN的思想是比较类似的)

2.5、 HashMap和HashTable 区别,HashTable线程安全吗/h2>

1.1、HashMap和Hashtable的区别
HashTable(线程安全)就是把HashMap套上了一个Synchronized

2.6、 进程间通信有哪几种方式/h2>

管道、消息队列、信号量、共享内存、套接字
无名管道( pipe ):
管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。

高级管道(popen):
将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程,这种方式我们成为高级管道方式。

有名管道 (named pipe) :
有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。

消息队列( message queue ) :
消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

信号量( semophore ) :
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。

信号 ( sinal ) :
信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。

共享内存( shared memory ) :
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。

套接字( socket ) :
套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

2.7、 JVM分为哪些区,每一个区干吗的/h2>

线程独占 : 栈 , 本地方法栈 ,程序计数器
线程共享 : 堆 , 方法区

程序计数器PC
线程私有的
它可以看做是当前线程所执行的字节码的行号指示器
内存区域中唯一一个没有规定任何OutOfMemoryError的区域

Java虚拟机栈
线程私有的
每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息
如果线程请求的栈深度大于虚拟机所允许的深度,将抛StackOverFlowError异常;
如虚拟机扩展时仍无法申请到足够的内存,就会抛出OutOfMemoryError异常

本地方法栈
与虚拟机栈非常相似,区别是虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则为虚拟机使用Native方法服务
也会抛出StackOverFlowError和OutOfMemoryError异常

Java堆
线程共享的
Java堆是GC管理的主要区域
在虚拟机启动时创建
存放对象实例,几乎所有的对象实例和数组都在这里分配内存。
如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常

方法区
线程共享的
用于存储已被虚拟机加载的类信息、常量、静态变量、即使编译器编译后的代码等数据
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常

运行时常量池
是方法区的一部分
用于存放编译器生成的各种字面量和符号引用
相对于Class文件常量池的一个重要特征是,具备动态性
运行时常量池是方法区的一部分,自然受到方法区内存的限制。当常量池无法再申请到内存时会抛出OutOfMemoryError异常

2.8、 JVM如何GC,新生代,老年代,持久代,都存储哪些东西/h2>

1.4、 说一说GC

2.9、 GC用的引用可达性分析算法中,哪些对象可作为GC Roots对象/h2>

可达性分析算法的思想:
从一个被称为GC Roots的对象开始向下搜索,如果一个对象到GC Roots没有任何引用链相连时,则说明此对象不可用。
在java中可以作为GC Roots的对象有以下几种:

虽然这些算法可以判定一个对象是否能被回收,但是当满足上述条件时,一个对象 不一定会被回收。当一个对象不可达GC Roots时,这个对象并不会马上被回收,而是处于一个死缓的阶段,若要被真正的回收需要经历两次标记。如果对象在可达性分析中没有与GC Roots的引用链,那么此时就会被第一次标记并且进行一次筛选,筛选的条件是是否有必要执行finalize()方法。当对象没有覆盖finalize()方法或者已经被虚拟机调用过,那么就认为是没必要的。

如果该对象有必要执行finalize()方法,那么这个对象将会放在一个称为F-Queue的队列中,虚拟机会触发一个finalize()线程去执行,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这还是因为如果finalize()执行缓慢或者发生了死锁,那么就会造成F-Queue队列一直等待,造成了内存回收系统的崩溃。GC对处于F-Queue中的对象进行第二次被标记,这时,该对象将被移除“即将回收”集合,等待回收。

2.10、 快速排序,过程,复杂度/h2>

快速排序,分治递归,对于每一段做如下处理:
从右向左第一个小于x的数放在原来左位置+1得那个地方,相反,从左向右第一个大于x的数放到原来右位置-1,一直到坐位置》=右位置,然后中间位置=原来左面的那个位置的数,在递归调用(l,i-1)和(i+1,r)

2.11、 什么是二叉平衡树,如何插入节点,删除节点,说出关键步骤。

对于每一个结点来说,子树和右子树都是二叉平衡树,左右子树的高度差不能大于1,如果插入删除使得高度差大于1了,就要进行旋转操作
插入:
如果有当前结点就返回false,就插入,如果还是二叉平衡树就返回true,插入的过程中如果不符合条件,就左旋右旋处理
删除:
(1)删除节点没有左子树,这种情况直接将删除节点的父节点指向删除节点的右子树。
(2)删除节点没有右子树,这种情况直接将删除节点的父节点指向删除节点的左子树。
(3)删除节点左右子树都存在,可以采用两种方式,
1:让删除节点左子树的最右侧节点代替当前节点
2:让删除节点右子树的最左侧节点代替当前节点

2.12、 TCP如何保证可靠传输次握手过程/h2>

TCP为了提供可靠传输:
(1)首先,采用三次握手来建立TCP连接,四次握手来释放TCP连接,从而保证建立的传输信道是可靠的。
(2)其次,TCP采用了连续ARQ协议(回退N,Go-back-N;超时自动重传)(自动重传请求(Automatic Repeat-reQuest,ARQ))来保证数据传输的正确性,使用滑动窗口协议来保证接方能够及时处理所接收到的数据,进行流量控制。
(3)最后,TCP使用慢开始、拥塞避免、快重传和快恢复来进行拥塞控制,避免网络拥塞。

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手: 建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手: 服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手: 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 完成三次握手,客户端与服务器开始传送数据.

2.13、 TCP和UDP区别/h2>

TCP与UDP区别总结
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接
2、TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。TCP通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
3、UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
4.每一条TCP连接只能是点到点的;UDP支持一对一、一对多、多对一和多对多的交互通信。
5、TCP对系统资源要求较多,UDP对系统资源要求较少。
为什么UDP有时比TCP更有优势br> UDP以其简单、传输快的优势,在越来越多场景下取代了TCP,如实时游戏。
(1)网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。
(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。
采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成影响。

2.14、 滑动窗口算法/h2>

大概意思:在一个数组或者其他链表中,确认左端点和右端点,这中间用和或者其他的存起来,一个一个的向右移动右端点,这个过程中可能因不符合条件要把左端点也右移,在这个过程中一直记录最大值或者最小值,(向右移动左端点就是在这个范围的和或者其他记录的数值删去左端点这个值)

2.15、 Linux下如何进行进程调度的/h2>

凉凉…………(这个不会,看也看不懂的那种)
1.先来先服务调度算法
  先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,
每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪
队列。在进程调度中采用FCFS算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。
该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。
2、基于优先级调度 (Priority Scheduling)
  在优先级调度算法中,每个进程都关联一个优先级,内核将CPU分配给最高优先级的进程。具有相同优先级的进程,按照
先来先服务的原则进行调度。
Aging就是指逐渐提高系统中长时间等待的进程的
优先级。我们可以每15分钟将等待进程的优先级加1。最终
经过一段时间,即便是拥有最低优先级的进程也会变成系统中最高优先级的进程,从而被执行。

优先级调度可以抢占式或者非抢占式的。当一个进程在Ready队列中时,内核将它的优先级与正在CPU上执行的进程的优先级
进行比较。当发现这个新进程的优先级比正在执行的进程高时:对于抢占式内核,新进程会抢占CPU,之前正在执行的进程
转入Ready队列;对于非抢占式内核,新进程只会被放置在Ready队列的头部,不会抢占正在执行的进程。
3、短进程优先(SCBF–Shortest CPU Burst First)
  最短CPU运行期优先调度算法(SCBF–Shortest CPU Burst First)
该算法从就绪队列中选出下一个“CPU执行期最短”的进程,为之分配处理机。
最短作业优先调度是优先级调度的特例。在优先级调度中我们根据进程的优先级来进行调度,在最短作业优先调度中我们
根据作业的执行时间长短来调度。
4、轮转法 (Round-Robin Scheduling) (RR)
  前几种算法主要用于批处理系统中,不能作为分时系统中的主调度算法,在分时系统中,都采用时间片轮转法。
简单轮转法:系统将所有就绪进程按FIFO规则排队,按一定的时间间隔把处理机分配给队列中的进程。这样,就绪
队列中所有进程均可获得一个时间片的处理机而运行。多级队列方法:将系统中所有进程分成若干类,每类为一级。
  RR调度算法转为分时系统设计,它与FCFS很像,但是加入了抢占。具体调度过程是:内核从Ready队列中选取第一个进程,
将CPU资源分配给它,并且设置一个定时器在一个时间片后中断该进程,调度Ready队列中的下一进程。很明显,RR调度
算法是抢占式的,并且在该算法的调度下,没有一个进程能够连续占用CPU超过一个时间片,从而达到了分时的目的。
5、高响应比优先调度算法
  (1) 如果作业的等待时间相同,则要求服务的时间愈短,其优先权愈高,因而该算法有利于短作业.
  (2) 当要求服务的时间相同时,作业的优先权决定于其等待时间,等待时间愈长,其优先权愈高,因而它实现的是先来先服务.
  (3) 对于长作业,作业的优先级可以随等待时间的增加而提高,当其等待时间足够长时,其优先级便可升到很高, 从而也可获得处理机.
  该算法照顾了短作业,且不会使长作业长期得不到服务
6、抢占式调度算法

  1. 非抢占式调度算法
    为每一个被控对象建立一个实时任务并将它们排列成一轮转队列,调度程序每次选择队列中的第一个任务投入运行.该任务完成后便把它挂在轮转队列的队尾等待下次调度运行.
  2. 非抢占式优先调度算法.
    实时任务到达时,把他们安排在就绪队列的对首,等待当前任务自我终止或运行完成后才能被调度执行.
  3. 抢占式调度算法
    1)基于时钟中断的抢占式优先权调度算法.
    实时任务到达后,如果该任务的优先级别高于当前任务的优先级并不立即抢占当前任务的处理机,而是等到时钟中断到来时,调度程序才剥夺当前任务的执行,将处理机分配给新到的高优先权任务.
    2)立即抢占的优先权调度算法.
    在这种调度策略中,要求操作系统具有快速响应外部时间中断的能力.一旦出现外部中断,只要当前任务未处于临界区便立即剥夺当前任务的执行,把处理机分配给请求中断的紧迫任务,实时进程调度,实时进程抢占当前。

2.16、 Linux下你常用的命令有哪些/h2>

这个最好是多用用比较好,直接跳过看一下个题

1、显示日期的指令: date
2、显示日历的指令:cal
3、简单好用的计算器:bc
怎么10/100会变成0呢是因为bc预设仅输出整数,如果要输出小数点下位数,那么就必须要执行 scale=number ,那个number就是小数点位数,
4、重要的几个热键[Tab],[ctrl]-c, [ctrl]-d
[Tab]按键—具有『命令补全』不『档案补齐』的功能
[Ctrl]-c按键—让当前的程序『停掉』
[Ctrl]-d按键—通常代表着:『键盘输入结束(End Of File, EOF 戒 End OfInput)』的意思;另外,他也可以用来取代exit
5、man
退出用q,
man -f man
6、数据同步写入磁盘: sync
输入sync,那举在内存中尚未被更新的数据,就会被写入硬盘中;所以,这个挃令在系统关机戒重新启劢乀前, 径重要喔!最好多执行几次!
7、惯用的关机指令:shutdown
此外,需要注意的是,时间参数请务必加入指令中,否则shutdown会自动跳到 run-level 1 (就是单人维护的登入情况),这样就伤脑筋了!底下提供几个时间参数的例子吧:
重启,关机: reboot, halt,poweroff
8、切换执行等级: init
Linux共有七种执行等级:
–run level 0 :关机
–run level 3 :纯文本模式
–run level 5 :含有图形接口模式
–run level 6 :重新启动
使用init这个指令来切换各模式:
如果你想要关机的话,除了上述的shutdown -h now以及poweroff之外,你也可以使用如下的指令来关机:
9、改变文件的所属群组:chgrp
10、改变文件拥有者:chown
他还可以顸便直接修改群组的名称
11、改变文件的权限:chmod
权限的设定方法有两种, 分别可以使用数字或者是符号来进行权限的变更。
–数字类型改变档案权限:
–符号类型改变档案权限:
12、查看版本信息等
13、变换目录:cd
14、显示当前所在目录:pwd
15、建立新目录:mkdir
不建议常用-p这个选项,因为担心如果你打错字,那么目录名称就回变得乱七八糟的
16、删除『空』的目录:rmdir
17、档案与目录的显示:ls
18、复制档案或目录:

来源:发呆哥o_o ….

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2020年7月21日
下一篇 2020年7月21日

相关推荐