Java基础

1 异常分类:

Throwable分errorexception.

2 JDK,JRE,JVM

JDK:普通用户只需要安装 JRE来运行 Java 程序。而程序开发者必须安装JDK来编译、调试程序。它提供了编译运行java程序所需的各种工具和资源,包括java编译器、java运行环境JRE,以及常用的java基础类库等,是整个java的核心。
JDK有三个版本,SE\EE\ME

  1. SE:标准版,是我们通常用的一个版本
  2. EE:企业版,
  3. ME:主要用于移动设备、嵌入式设备上的java应用程序(相对来说现在用的很少了)

JDK,JRE,JVM三者的区别与联系

  1. JDK用于开发,是给开发人员用的,JRE
    用于运行java程序,和JVM是给普通用户使用的。如果只是运行Java程序,可以只安装JRE,无序安装JDK。也就是说:使用JDK开发完成的java程序,交给JRE去运行。
  2. JDK包含了JRE,JDK 和 JRE 中都包含
    JVM。也可以说JDK是JRE+Java的开发工具。JRE包含了JVM+Java语言的核心类库。

3 索引的本质

4 红黑树和B+树

红黑树 自平衡的二叉查找树。假如寸500w的数据如果是极端的情况下要查找的数据在叶子节点上,就要查找树的高度,假设高度是30那就得要30次的磁盘IO才能找到叶子节点上去。本身磁盘IO就效率不高,还要30次的磁盘IO,那得多慢,用户肯定等不及,所以红黑树也是有弊端。
假如要存储俩千万行记录,假如我们能不能控制它的高度最多是4,树无非就是纵向和横向,我们想它纵向小就可以扩展他横向,我一个节点给他分几十个索引,让它去分叉,每个叉分大一点空间。就是B树。

但是凡事有个度,你不可能把全部数据,几千万个索引放一个节点里面,mysql中设置了节点大小16k。(假设索引就是主键类型是bigint就是8B,然后每俩元素之间的空白部分存的下一个节点的地址6B,16kB/14B=1170) 假设叶子data加索引1kb 一共就可以有1170117016大概俩千多万

所以你要是俩千万的记录放在叶子节点上面 也只要俩次磁盘IO。树的高度只有三,就能存储几千万行记录,我查找某个索引即便在叶子节点也只要俩三次磁盘IO就能查到了,而且一般来说mysql的底层索引他的根节点常驻在内存,俩千万行记录,你要查到叶子节点,只要俩次磁盘IO就搞定了。

MyISAM存储引擎索引实现解析

存储引擎是形容表的,(索引元素30的叶子节点data元素就是索引所在行的磁盘文件地址指针)

MyIsam跨俩个文件,先判断你col1有没有索引,有索引col1是索引字段,就去MYI文件查找那个索引所在行的磁盘文件地址,根据磁盘文件地址指针在MYD文件一次性定位到那一行元素。
MyISAM(.frm表结构,.MYI索引文件,.MYD数据文件)
InnoDB(.frm表结构,.ibd数据文件和索引文件合并)

非聚集索引(MyISAM这存储引擎它的主键索引)就是它索引和数据是分开存储的,在俩个文件里。
InnoDB的主键索引叫聚集索引(也叫聚簇索引)只有主键索引叶子节点才存储整张表的数据,非主键索引比如二级索引它的叶子节点存的是主键

3.为什么推荐整形的自增主键(而不用UUID,UUID刚好相反也不是整形也不是自增的),因为像我们要查找一个元素查找30这个索引元素所在行,他要把某个节点先load到内存,然后在内存里面不断地去比大小,然后在逐个的去load到某一个节点,也就是说在整个查找过程中他可能要大量的去做数据的比对,那肯定是俩个整形比对快,UUID那种字符串abc…和ab12…比对还要转换成ASCAII码去比对而且只能一个字母一个字母去比对 最坑爹的是要是前面字符都一样还得比到最后才能知道大小。所以字符串比大小比整形慢多了。
mysql索引除了用B树(99.99%)还有一个用哈希表(将字段里的索引值做一次hash运算放到一个表里面,然后吧这一索引所在行的磁盘文件地址指针放在表里同一行的另外一列)任意一行数据元素->所在磁盘文件地址指针
3.2 自增,假如我们是一个范围查找(col>20)我们就可以从根节点快速的定位到这个元素,然后这节点里面元素遍历完后,从左到右依次顺藤摸瓜顺着指针把后面节点元素全部load出来就行了,如果小于20我们就顺着逆向的指针往前去查找。 如果是B树没有指针的话,要大于二十,我们快速定位到元素,只能把20在的节点里面大于20的元素load到里面,下一个节点我是没办法直接去找,又要从根节点往下去遍历(也就是要大于20,没有指针,每一次都要从根节点去找,再把它合并那是非常慢的)

JDK体系和jvm

.java文件通过过javac命令编译成字节码文件,然后通过java命令把它放到java虚拟机里面去运行。java语言支持跨平台运行(因为选了不同平台的jdk它里面的jvm,就会针对这个平台有对应的实现)JVM从软件层面屏蔽不同操作系统在底层硬件与指令上的区别

运行时数据区

栈帧:一个线程当执行到一个方法时,JVM马上会给这个方法分配一块自己独立的那块内存区域,我们把一个方法对应的内存区域叫做方法对应的栈帧内存区域。

(栈帧里面包括:局部变量表、操作数栈、动态链接、方法出口)对象类型的局部变量存的是堆里面实际对象的一个内存地址说白了就是指针(栈->堆)

程序计数器:程序当cpu多线程切换的时候,它切回到当前线程的时候会根据程序计数器的位置知道接下来该执行哪些代码。
方法区:(包括:常量,静态变量,类信息)jdk1.8前位于永久代,jdk1.8后移除永久代替换为元空间
对象类型的静态变量存的是堆里面实际对象的一个内存地址说白了就是指针(方法区->堆)
本地方法栈:本地方法运行时需要的那块内存区域(本地方法里面的局部变量放在本地方法栈里)
:new的对象

  1. 对象动态年龄判断机制:一批对象总大小大于这块Survivor区内存的50%,就可以直接进入老年代了
  2. 长期存活对象进入老年代:对象每熬过一次MinorGc年龄就加1岁,如果有幸活过15就晋升老年代
  3. 大对象直接进入老年代:(需要大量连续内存空间的对象,像字符串,数组)JVM有个参数设置大对象大小,对象超过设置大小直接进入老年代。(为了避免为大对象分配内存时的复制操作而降低效率)

能否对JVM调优(减少fullgc次数),让其几乎不发生Full Gc(老年代满了会触发fullgc,一次fullgc它的STW时间是非常长的,fullgc会收集整个堆以及方法区的内存区域,收集内存空间太大所以它STW时间非常长): 堆大小不变(3G)设置年轻代变成2G(edean区和servivor8:1:1则edean1.6G,servivor200M)

多核并发缓存架构

如果cpu直接和内存打交道,无论cpu有多快会被内存限制掉,所以会在cpu和主内存之间架一级高速缓存,也就是说cpu要从主内存读取数据进行运算它不在是和主内存直接交互了,而是把主内存中的数据读取到高速缓存,而cpu读写数据的话会更cpu缓存直接打交道,回头cpu缓存再把数据同步给主内存

JMM内存模型(java线程内存模型)

volatile关键字:可以保证共享访问变量在多线程之间的的可见性
JMM缓存不一致问题:

  • 总线加锁(性能太低):cpu从主内存读取数据到高速缓存,会在总线对这个数据加锁,使其他cpu没法去读或写这个数据,直到这个cpu使用完数据释放锁后其他cpu才能读取该数据,说白了俩个线程想并行执行的,虽然是并行运行的但是可能访问到同一个变量时因为加锁,在内存里面是要排队的,就是并行的代码被换为了一个串型的逻辑,性能就不高
  • MESI 缓存一致性协议 :多个cpu从主内存读取同一个数据到各自的高速缓存,当其中某个cpu修改了缓存里的数据,该数据马上同步回主内存,其他cpu通过 总线嗅探机制 可以感知到数据的变化从而将自己缓存里的数据失效。(底层实现主要通过lock前缀指令,会锁定该内存区域的缓存并回写到主内存)

volatile 可见性、原子性与有序性

  • 并发编程三大特性:可见性,原子性,有序性

  • volatile保证可见性,有序性,但是不保证原子性,保证原子性需要借助synchronized这样的锁机制。

servlet3.x新规范解读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值