当前位置: 首页 > article >正文

计算机基础知识复习1.1

HashMap的put过程

1.根据要添加的键的哈希码计算在数组中的位置(索引)

2.检查该位置是否为空(即没有键值对存在)

3.如果该位置已经存在其他键值对,检查该位置的第一个键值对的哈希码和键是否与添加的键值对相同

4.如果第一个键值对的哈希码和键不相同,则需要遍历链表或红黑树来查找有相同的键

5.检查链表长度是否到达阈值

6.检查负载因子是否超过阈值

7.扩容操作

类加载器

启动类加载器<-扩展类加载器<-应用程序类加载器<-用户自定义加载器

类加载过程

加载:通过类的全限定名(包名+类名),获取到该类的.class文件的二进制字节流,将二进制字节流所代表的静态存储结构,转化为方法区运行时的数据结构,在内存中生成一个代表该类的Java.lang.class对象,作为方法区这个类的各种数据的访问入口

验证:确保class文件的字节流包含的信息,符合当前虚拟机的要求,保证这个被加载的class类的正确性,不会危害到虚拟机的安全,验证阶段大致会完成以下四个阶段的检验动作,文件格式校验,元数据验证,字节码验证,符号引用验证

准备:为类中的静态字段分配内存,并设置默认的初始值,比如int类型的初始值是0

解析:虚拟机将常量池中的符号引用直接替换为直接引用,指向内存中的目标

初始化:执行类的构造器方法

使用:使用类或者创建对象

卸载

实现RejectedExecutionHandler接口定义自定义拒绝策略,自定义拒绝策略负责将线程池暂时无法处理的任务入库(保存到Mysql中)

继承BlockingQueue实现一个混合式阻塞队列,该队列包含JDK自带的ArrayBlockingQueue,另外该混合式阻塞队列需要修改取任务的逻辑,也就是重写take()方法,取任务时优先从数据库中读取最早的任务,数据库无任务时再从ArrayBlockingQueue读取任务 

FixedThreadPool:固定线程数量的线程池,该线程池中的线程数量始终不变,当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务

SinglrThreadExecutor:只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务

CachedThreadPool: 可根据实际情况调整线程数量的线程池,线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程,若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务,所有线程在当前任务执行完毕后,将返回线程池进行复用

ScheduledThreadPool:给定的延迟任务运行任务或定期执行任务的线程池

JVM调优的参数

设置堆空闲大小和最大大小,为了防止垃圾收集器在初始大小,最大大小之间收缩堆而产生额外的时间,通常把最大,初始大小设置为相同的值

虚拟机栈的设置 每个线程默认会开启1M的内存,用于存放栈帧,调用参数,局部变量等,但一般256k就够用。通常减少每个线程的堆栈,可以产生更多的线程。

调整年轻代Eden区和两个Survivor区的大小比例

调整年轻代晋升老年代的阈值

设置垃圾回收收集器 -XX +UseG1GC

G1垃圾回收器(JDK9 默认的垃圾回收器)

年轻代垃圾回收

初始时,所有区域都处于空闲状态

创建了一些对象,挑出一些空闲区域作为伊甸园区存储这些对象

当伊甸园需要垃圾回收时,挑出一个空闲区域作为幸存者区,用复制算法复制存活对象,需要暂停用户线程

并发标记

当老年代占用内存超过阈值(默认为45%) 触发并发标记,这时无需暂停用户线程

混合收集

不会对所有老年代区域进行回收,而是根据暂停时间目标优先回收价值高(存活对象少)的区域

虚拟线程

JVM维护了一个由专用ForkJoinPool创建和维护的平台线程池。最初,平台线程的数量等于CPU核心的数量,最多不能超过256个

对于每个创建的虚拟线程,JVM都会将其执行调度到一个平台线程上,临时将虚拟线程的堆栈块从堆复制到平台线程的堆栈中,我们说平台线程变成了虚拟线程的载体线程

CPU密集型任务(N+1):这种任务消耗的主要是CPU资源,可以将线程数设置为N(CPU核心数)+1 比CPU核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其他原因导致的任务暂停而带来的影响。一旦任务暂停,CPU就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用CPU的空闲时间

I/O密集型任务(2N):这种任务应用起来,系统会用大部分的时间来处理I/O交互,而线程在处理I/O的时间段内不会占用CPU来处理,这时就可以将CPU交出给其他线程使用。

内存屏障

写-写屏障:在对bolatile变量执行写操作之前,会插入一个写屏障,这确保了在该变量写操作之前的所有普通写操作都完成,防止了这些写操作被移到volatile写操作之后

读-写屏障:在对volatile变量执行读操作之后,会插入一个读屏障。他确保了对volatile变量的读操作之后的所有普通读操作都不会被提前到volatile读之前执行,保证了读取到的数据是最新的

写-读屏障:发生在volatile写之后和volatile读之前,这个屏障确保了volatile写操作之前的所有内存操作都不会被重排序到volatile读之后,同时也确保了volatile读操作之后的所有内存操作都不会被重排序volatile写之前

GC Root的对象

1.虚拟机栈中正在引用的对象

2.本地方法栈中正在引用的对象

3.静态属性引用的对象

4.方法区中常量引用的对象

select/poll

select实现多路复用的方式是,将已连接的socket都放到一个文件描述符集合,然后调用select函数将文件描述符集合拷贝到内核里,让内核来检查是否有网络事件产生,检查的方式很粗暴,就是通过遍历文件描述符集合的方式,当检查到有事件产生后,将此socket标记为可读或可写,接着再把整个文件描述符集合拷贝回用户态里,然后用户态还需要再通过遍历的方法找到可读可写的socket,然后再对其处理

poll不再使用bitsMap来存储所关注的文件描述符,取而代之用动态数组,以链表形式来组织,突破了select的文件描述符个数限制,当然还会受到系统文件描述符限制

epoll

epoll在内核里使用红黑树来跟踪进程所有待检测的文件描述字,把需要监控的socket通过epoll_ctl()函数加入内核中的红黑树里,红黑树是个高效的数据结构,增删改一般时间复杂度是O(logn)  epoll因为在内核维护了红黑树,可以保存所有待检测的socket,所以只需要传入一个待检测的socket,减少了内核和用户空间大量的数据拷贝和内存分配 

epoll使用事件驱动机制,内核里维护了一个链表来记录就绪事件,当某个socket有事件发生时,通过回调函数内核会将其加入到这个就绪事件列表中,当用户调用epoll_wait()函数时,只会返回有事件发生的文件描述符的个数,不需要像select/poll那样轮询扫描整个socket集合,大大提高了检测的效率


http://www.kler.cn/a/461857.html

相关文章:

  • 【MongoDB详解】
  • STM32 和 ESP32
  • 下载linux aarch64版本的htop
  • Alist-Sync-Web 网盘自动同步,网盘备份相互备份
  • Android 模拟器系统镜像选择指南
  • PyTorch AMP 混合精度中grad_scaler.py的scale函数解析
  • 【机器学习 | 数据挖掘】时间序列算法
  • 小程序组件 —— 23 组件案例 - 轮播图图片添加
  • Excel 面试 03 多个条件函数 SUMIFS
  • Django-Easy-Audit 实战:轻松实现数据审计
  • 【2024最新】基于Python+Mysql+PyQT5的数学函数绘图软件Lw+PPT
  • Unity3D仿星露谷物语开发12之创建道具列表
  • iOS 中的 nil、Nil、NULL、NSNull 僵尸对象和野指针
  • Disruptor 有哪些典型的使用场景?
  • Frontend - 分页(针对 python / Django )
  • SpiderFlow平台v0.5.0内置变量及自定义函数
  • AAL省电效果对比
  • trie树算法--c语言
  • 解决Spring boot集成quartz时service注入失败为null的问题
  • 【目标跟踪】checkpoint文件到底是什么?
  • 网页单机版五子棋小游戏项目练习-初学前端可用于练习~
  • 基于W2605C语音识别合成芯片的智能语音交互闹钟方案-AI对话享受智能生活
  • MySQL DBA需要掌握的 7 个问题
  • 使用 Vue CLI 创建 Vue.js 项目的详细指南
  • 【DevOps】Jenkins部署
  • Java jni调用nnom rnn-denoise 降噪