1. JMM内存模型有了解过吗
所谓JMM内存模型 ,是java提供的一套内存模型,屏蔽不同系统的内存模型的差异性,是java对于并发编程的一组规范和要求,其抽象了线程和主内存之间的关系,还规定了从Java代码到cpu可执行指令的转换中的关于并发编程的原则和规范,其目的是简化多线程编程,增强程序的可移植性。
2. Java内存区域和JMM内存模型有什么区别
java内存区域和JMM内存模型是两个完全不同的东西
java内存区域和java虚拟机运行时区域相关,定义了java运行时如何分区存储数据,如堆主要存放对象实例数据
JMM内存模型则是Java提供的一套内存模型,屏蔽了不同操作系统的内存模型差异,是Java对于并发编程的一组规范和要求,其抽象了线程和主内存的关系,如线程之间的共享变量必须存储在主内存中,定义了从java代码到可执行CPU指令的转换过程中关于并发编程的原则和规范,用于简化多线程开发,增强程序的可移植性
3. java内存区域有哪些
堆,用于存放运行中的实例对象,分为新生代,老年代,字符串常量池(jdk1.7之后),静态变量(jdk1.7之后)。是垃圾回收的主要区域
栈,分为虚拟机栈和本地方法栈,每个线程创建时会创建线程自己的栈空间,java中的方法调用是通过栈来实现的,方法调用数据通过栈进行传递,每一次方法调用都会有一个对应的栈帧入栈,每一个方法调用结束,都会有一个对应的栈帧出栈
方法区,永久代(jdk1.8后被移到本地内存变为元空间,二者皆为方法区的实现),逻辑上和堆是连续的,物理上永久代和堆是连续的(同在虚拟内存),元空间和堆不连续(在本地内存),包括运行时常量池,方法表,字符串常量池(jdk1.7之前),静态变量(jdk1.7之前),类的相关信息
程序计数器,每个线程都有自己的计数器,保存的是线程当前执行指令的位置
4. java内存溢出和内存泄漏
java内存溢出常指OOM,指由于内存不足导致的运行时异常,根据区域不同分为
堆内存溢出,通常由于大对象创建过多导致超出堆内存限制,也可能是由于堆内存分配过小。
栈内存溢出,通常由于递归方法调用导致栈内存超出限制,也可能时由于栈内存分配过小。
方法区内存溢出,通常由于类数量过多导致超出容量限制,如通过反射,动态代理生成过多的类,也可能是方法区内存设置过小或时系统内存不足
内存泄漏,程序中存在为释放的内存占用,导致可用内存不足导致内存溢出
java内存泄漏通常指一个或多个对象不再被使用,却无法被垃圾收集器回收的情况,通常由于以下几种情况导致:
静态字段持有对象,当此对象保存过多的数据并且在不需要时未主动清除时,会导致垃圾收集器无法回收对应内存。
未关闭的资源,如打开流,文件或连接时,在使用完后未关闭对应的流,连接或文件,会导致打开过多的连接实例从而导致内存缓慢耗尽。
通过线程池控制线程并发数量时,在ThreadLocal中存储信息,因为线程池中的线程不会被销毁,如果不手动清除,会导致ThreadLocal中的信息占用内存一直未被回收导致内存耗尽
总而言之内存泄漏可能会导致内存溢出,而内存溢出不一定是因为内存泄漏,也可能是其他原因
5. synchronized锁有了解过原理吗
在jdk6之前的synchronized是jvm底层基于操作系统的mutex lock实现一个同步锁,通过关键字synchronized标记方法是实现方式为执行此方法前会先查看此方法是否为synchronized修饰,如果是则先获取对应的monitor,普通方法获取的是对象实例的monitor,静态方法获取的是类的monitor,获取到则执行,获取不到则阻塞等待获取,执行完成后释放对应的monitor,而通过synchronized修饰代码块时则是通过monitorenter和monitorexit两条指令实现,在同步代码块前执行monitorenter获取指定对象monitor,在同步代码块结束时执行monitorexit释放monitor。
在jdk6之后synchronized得到了升级,通过增加了不同状态的锁作为过渡,按到从低到高分别为偏向锁,轻量级锁,重量级锁(即为具有完整monitor功能的锁),
偏向锁是一种偏向于第一次获取到它的线程的锁,已经获取到的线程再次获取时无需任何同步操作(实现了锁的可重入功能),而当有其他线程尝试获取此锁时,偏向锁结束,如果并发数不大的情况则升级为轻量级锁,
相比于重量级锁使用操作系统的互斥量实现,轻量级锁基于CAS操作实现,尝试比较并交换,一般通过CAS的方式获取锁,不阻塞线程采用循环等待的方式,成功获取到,则为轻量级锁,自旋获取失败一定次数则升级为重量级锁。
自旋锁,是轻量级锁升级为重量级锁的一个过渡锁,通过CAS操作+失败重试实现
6. 乐观锁,悲观锁介绍和实现原理
悲观锁总是假定最坏的情况,认为共享资源每次被访问都会出现问题,每次在获取共享资源时都会上锁,这样其他线程想拿到这个资源就必须等到锁被持有者释放,也即是,共享资源每次只给一个线程使用,其他线程阻塞,用完之后在转让给其他线程。java中synchronized和ReentrentLock等独占锁都属于悲观锁
乐观锁总是假定最好的情况,认为共享资源每次被访问不会出现问题,无需加锁也无需等待,只在需要修改时去验证原数据是否被修改过,具体实现方式一般有两种,版本号机制,CAS算法,自旋锁即是乐观锁的一个实现,其通过CAS和失败重试实现
版本号机制,一般是通过在一条数据中加入版本号,每次修改会对比数据版本号是否变动,变动则驳回,未变动则提交修改并且更新版本号
CAS算法全称为Compare And Swap,比较与交换,其是一个原子操作,底层依赖于一条CPU的原子指令,其思想为用一个预期值和将要更新的值进行比较,相等则更新,不相等则说明其值已被其他线程更改,则驳回。当多个线程同时通过CAS操作更新一个值时,只有一个会胜出,其他的都会失败,但失败的线程不会被挂起,而是会被告知失败,且允许重试或者放弃。
7. MYSQL数据库优化有哪几种方式
索引优化:
对经常查询的数据创建索引可以提升查询速度,
避免创建过多索引,会影响插入,更新和删除的效率。
多列联合查询建立联合索引可以提高性能加速同时多个条件的查询
使用覆盖索引可以大幅加速查询速度,覆盖索引即索引本身包含查询所需的全部数据
选择合适的字段类型可以节省空间并增加查询效率,例如根据长度选择int或bigint,vachar或text
查询优化:
使用Explan分析sql查询计划,从而优化查询可能出现的问题,如全表扫描,未走索引
避免使用select * 语句
使用limit限制返回的数据量,避免返回大量无用数据
合理使用where语句,确保where语句的条件能优先利用索引
分库分表:对于大规模数据量可以采用分库分表策略,将数据分配到多个数据库和表中,减少单个表的大小,从而提升表的查询速度。水平分割(按照某个条件将数据分配到不同的表中)和垂直分割(将不同类型的数据存储到不同的表中)是常见的分库分表策略。
读写分离:
使用主从复制将读请求分配到多个从服务器从而减轻主服务器压力,提升系统整体并发能力,主库处理写操作,从库处理读操作。
配置负载均衡策略,将请求合理的分配到多个数据库实力,检定单个数据库压力
8. 索引失效的场景有哪些
使用联合索引时未遵循最左匹配原则,如联合索引为(a,b,c),而在条件语句中使用where b=0 and c= 0条件,所以联合索引最左列一般使用最频繁访问的数据
使用模糊匹配like 时通配符 %在开头的情况,如like "%张"的情况
使用了select * 语句
索引列使用了函数,或者运算或导致索引失效
条件语句使用or连接时,有一个条件不为索引
参数类型和索引列类型不一致,发生隐式转换会导致索引失效
两列作比较,即使两列都创建了索引,也不会走索引
查询条件使用is not null时,不走索引,使用is null 时正常走索引
posted @
2025-07-30 13:49
JiaoHu'ang
阅读(
18 )
评论()
收藏
举报