面试记录(面试记录需要记录什么)

  本篇文章为你整理了面试记录(面试记录需要记录什么)的详细内容,包含有面试记录表模板 面试记录需要记录什么 面试记录员一般怎么记录的 面试记录表 面试记录,希望能帮助你了解 面试记录。

  当进程运行在ring3级别时为用户态,ring0级别时为内核态

  有些操作需要有内核权限才能进行,那么有三种由用户态切换到内核态的情况:

  系统调用:操作系统封装内核指令,统一管理硬件资源,然后向用户程序提供系统服务,用户程序进行系统调用,操作系统进行检查确保安全然后再进行相应的资源访问操作。比如malloc(),print()调用write()系统输出字符串

  异常事件:当cpu正在运行用户态程序,发生不可预知的异常事件,就会转用户态,比如缺页中断。

  外围设备的中断:当外围设备完成请求就会向CPU发出中断信号,此时cpu暂停下一条要执行的指令,去执行中断信号所对应的程序

  相同点和不同点:都是中断,但是系统调用是主动,其他都是被动

  用户态和内核态线程的映射关系

  一对一(内核线程实现)

  程序使用轻量级进程和内核线程产生映射

  缺点:轻量级进程的数量有限制,执行效率低

  多对一(用户线程实现)

  优点:用户线程数量几乎无限制,执行效率高

  缺点:一个用户线程阻塞,其他线程也会阻塞

  多对多

  UT 用户态线程 LWP 轻量级线程 KLT 内核态线程

  优点:

  一个用户线程的阻塞不会导致所有线程的阻塞,因为此时还有别的内核线程被调度来执行。

  多对多模型对用户线程的数量没有限制。

  在多处理器的操作系统中,多对多模型的线程也能得到一定的性能提升,但提升的幅度不如一对一模型的高。在现在流行的操作系统中,大都采用多对多的模型。

  用户态线程:切换代价小,高并发但是容易阻塞

  内核态线程:处理能力高,切换代价大

  Java线程的实现

  虚拟机规范中并没有限定java线程需要使用哪种线程模型,要根据不同的平台来说,但是无论使用哪种线程模型,java程序的编码和运行都是没有差异的

  Java线程调度

  线程调度有两种:协同调度和抢占调度

  协同:自己分配时间,自己切换

  抢占:系统分配时间,系统决定线程的切换

  java线程采用抢占调度

  java线程的6种状态

  新建———-运行———无限期等待——–限期等待———阻塞——结束

  操作系统线程的几种状态

  新建———就绪————等待————运行———–结束

  java和操作系统的线程对应关系

  1.2之前(绿色线程 1:N),程序员为jvm开发了一个线程调度内核,映射到操作系统层面就是用户态线程;

  1.2(1:1)之后,jvmU型安泽了操作系统原生线程模型,映射到操作系统层面就是内核态线程,通过系统调用,将程序的线程交给了操作系统内核进行调度。

  通过创建过程来理解

  Java的Thread对象:仅仅是一个Java对象

  JVM的JavaThread对象:连接着java的Thread对象与OS对象

  JVM的OSThread对象:一个工具类,对OS线程API进行了功能性封装

  流程图:

  JVM_StartThread核心做了两件事情:

  1.创建JavaThread对象

  ​ (1) 设置jvm执行run方法的跳板

  ​ (2) 调用os::create_thread创建OSThread对象及操作系统线程完成三者的关联

  ​ os::create_thread做了一下这些:

  ​ 创建OSThread对象,将JavaThread对象与OSThread对象进行关联

  为开发人员提供创建和管理线程的一套API

  三个主要的线程库:

  1)POSIX Pthreads:可以作为用户或内核库提供,作为 POSIX 标准的扩展

  2)Win32 线程:用于 Window 操作系统的内核级线程库

  3)Java 线程:Java 线程 API 通常采用宿主系统的线程库来实现,也就是说在 Win 系统上,Java 线程 API 通常采用 Win API 来实现,在 UNIX 类系统上,采用 Pthread 来实现。

  操作系统对于锁的实现

  在硬件层面,CPU提供了原子操作、关中断(可解决单核情况下两个线程同时获得锁)、锁内存总线的机制(解决多核情况下两个线程同时获得锁);OS基于这几个CPU硬件机制,就能够实现锁;再基于锁,就能够实现各种各样的同步机制(信号量、消息、Barrier等等等等)

  synchronized的底层实现

  是通过对象内部的一个监视器锁(monitor)实现的,监视器锁有时通过操作系统的互斥锁来实现的,而且现在主流的java虚拟机实现中,java的线程是映射到操作系统原生的内核线程中的,那么线程的阻塞或唤醒,就涉及到用户态和内核态的转换中,所以是重量级锁。

  是一种块结构的同步语法,经过javac反编译之后,会在同步块的前后分别生成monitorenter和monitorexit两个字节码指令,这两个指令都需要一个reference类型的参数来指明加锁解锁的对象,如果synchronized明确了对象参数。就以这个对象的引用作为reference,如果没有指定,那就根据修饰的方法类型,来决定是区代码所在的对象实例还是相应的class对象。

  反射的性能优化

  两个地方导致性能差:getMethod和invoke,反射是一个解释操作,临时告诉jvm应该做什么

  优化思路1:缓存Method,不重复调用getMethod

  优化思路2:借助ASM框架,使用reflectAsm,让invoke变成直接调用

  借反射的getDeclaredMethods获取目标类的所有方法,然后动态生成一个继承于MethodAccess 的子类SimpleBeanMethodAccess,动态生成一个Class文件并load到JVM中。

  SimpleBeanMethodAccess中所有方法名建立index索引,index跟方法名是映射的,根据方法名获得index,SimpleBeanMethodAccess内部建立的switch直接分发执行相应的代码,这样methodAccess.invoke的时候,实际上是直接调用。

  hashmap在jdk1.7的死循环

  多线程头插法造成的,线程2已经完成扩容散列,链表变成了倒序,线程1再进行扩容,将倒序链表变成了一个正序链表,从而形成环形链表,在使用get方法时造成死循环。

  ArrayList

  首先有三种构造方法(有参,无参,指定集合参数组成的列表)

  主要就是三个方法:

  1.ensureCapacityInternal得到最小扩容量,并进行扩容

  2.ensureExplicitCapacity//判断是否需要扩容,如果最小扩容量大于数组现在的长度就调用grow方法

  3.grow进行位运算,扩容1.5倍,并进行判断是否超出数组的最大容量。

  始化数据量为0,add时变为10,当 要 add 进第 1 个元素时,minCapacity 为 1,在 ensureCapacityInternal的Math.max()方法比较后,minCapacity 为 10 ,

  最好在 add 大量元素之前用 ensureCapacity 方法(因为是public修饰),以减少增量重新分配的次数

  Set Map

  以上就是面试记录(面试记录需要记录什么)的详细内容,想要了解更多 面试记录的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: