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

java每日问题

一,什么时聚集索引什么时非聚集索引
聚集索引就是基于主键创建的索引除了主键索引以外的其他索引被称为非聚集索引也叫二级索引由于在innodb引擎里面一张表的数据对应的物理文件本事就是按照B+树来组织的一种索引结构而聚集索引就是按照每张表的主键来构建一颗B+树然后叶子结点存储每一张表的每一行数据记录所以基于innodb这样一个特性聚集索引并不仅仅是一种索引类型还代表着一种数据的存储方式同时也意味着每个表里面必须有一个主键,如果没有主键innodb会默认选择或者添加一个隐藏列作为主键索引来存储这个表的数据行,一般情况下是建议使用自增Id作为主键这样的话id本身具有连续性使得对应的数据也会按照顺序存储在磁盘上写入性能和搜索性能都很高否则如果我们使用uuid这种随机id那么在频繁插入数据的时候就会导致随机磁盘IO从而导致性能比较低。需要注意的是innodb只能存在一个聚集索引原因很简单如果存在多个聚集索引那么意味着这个表里面的数据会存在多个副本造成磁盘空间浪费以及数据维护困难的问题由于在innodb里面主键索引表示的是一种数据存储结构所以如果是基于非聚集索引来查询一条完整记录最终还是需要访问主键索引来检索。
二,什么是双亲委派
首先简单说一下类的加载机制就是我们自己写的java源文件到最终的运行必须要经过编译和类加载两个阶段编译的过程就是把Java编译成.class文件。类加载的过程呢就是把.class文件装载到jvm内存里面,装载完成以后就会得到一个class对象,我们就可以使用new关键字来实例化这个对象,而类加载的过程需要涉及到类加载器 jvm在运行中会产生三个类加载器,这三个类加载器组成了一个层级关系,每个类加载器分别去加载不同作用范围的jar包比如
(1)Bootstrap ClassLoader(启动类加载器) :主要负责加载Java核心类库,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。
(2)Extention ClassLoader(扩展类加载器):主要负责加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。
(3)Application ClassLoader(应用程序类加载器) :主要负责加载当前应用的classpath下的所有类
除了系统提供的类加载器以外还可以通过ClassLoader这个类来实现自定义类加载器去满足一些特殊场景的需求
而父委派模型就是按照类加载器的层级关系逐层进行委派比如需要加载一个class文件的时候首先会把这个class的查询和加载委派给父加载器去执行如果父加载器都无法加载在尝试自己去加载这个class。
这样设计的好处呢我认为的好处呢有几个
(1)安全性 因为这种层级关系实际上代表的是一种优先级也就i是所有的类加载优先给BootstrapClassLoader 那么对于核心类库中的类就没办法被破坏,比如自己去写一个java.lang.String最终还是会交给启动类加载器来加载,在加上每个类加载器的作用范围,那么自己写的java.lang.String就没有办法去覆盖类库中的类。
(2)这种层级关系的设计可以避免重复加载,导致程序混乱的问题,因为如果父类加载器已经加载过了那么子类就没有必要去加载了这就是整个类加载器的工作原理
三.Redis 和 Mysql 如何保证数据一致性
一般情况下,Redis 用来实现应用和数据库之间读操作的缓存层,主要目的是减少数据库 IO,还可以提升数据的 IO 性能。这是它的整体架构。
当应用程序需要去读取某个数据的时候,首先会先尝试去 Redis 里面加载,如果命中就直接返回。如果没有命中,就从数据库查询,查询到数据后再把这个数据缓存到 Redis 里面。
在这样一个架构中,会出现一个问题,就是一份数据,同时保存在数据库和 Redis里面,当数据发生变化的时候,需要同时更新 Redis 和 Mysql,由于更新是有先后顺序的,并且它不像 Mysql 中的多表事务操作,可以满足ACID 特性。所以就会出现数据一致性问题。
在这种情况下,能够选择的方法只有几种。
先更新数据库,再更新缓存先删除缓存,再更新数据库如果先更新数据库,再更新缓存,如果缓存更新失败,就会导致数据库和 Redis中的数据不一致。
如果是先删除缓存,再更新数据库,理想情况是应用下次访问 Redis 的时候,发
现 Redis 里面的数据是空的,就从数据库加载保存到 Redis 里面,那么数据是
一致的。但是在极端情况下,由于删除 Redis 和更新数据库这两个操作并不是原
子的,所以这个过程如果有其他线程来访问,还是会存在数据不一致问题。
所以,如果需要在极端情况下仍然保证 Redis 和 Mysql 的数据一致性,就只能
采用最终一致性方案。
比如基于 RocketMQ 的可靠性消息通信,来实现最终一致性。
四。死锁的发生原因和怎么避免
死锁,简单来说就是两个或者两个以上的线程在执行的过程中,争夺同一个共享
资源造成的相互等待的现象。
如果没有外部干预,线程会一直阻塞无法往下执行,这些一直处于相互等待资源
的线程就称为死锁线程。
导致死锁的条件有四个,也就是这四个条件同时满足就会产生死锁。
互斥条件,共享资源 X 和 Y 只能被一个线程占用;请求和保持条件,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;不可抢占条件,其他线程不能强行抢占线程 T1 占有的资源;
循环等待条件,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。导致死锁之后,只能通过人工干预来解决,比如重启服务,或者杀掉某个线程。所以,只能在写代码的时候,去规避可能出现的死锁问题。按照死锁发生的四个条件,只需要破坏其中的任何一个,就可以解决,但是,互斥条件是没办法破坏的,因为这是互斥锁的基本约束,其他三方条件都有办法来破坏:对于“请求和保持”这个条件,我们可以一次性申请所有的资源,这样就不存在等待了。对于“不可抢占”这个条件,占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源,这样不可抢占这个条件就破坏掉了。对于“循环等待”这个条件,可以靠按序申请资源来预防。所谓按序申请,是指资源是有线性顺序的,申请的时候可以先申请资源序号小的,再申请资源序号大的,这样线性化后自然就不存在循环了。


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

相关文章:

  • m4a怎么转换成mp3,4招搞定
  • 2023年全国最新道路运输从业人员精选真题及答案61
  • 一文带你上高速入门linux(含常用命令语法、说明、举例)
  • 数据治理-数据质量篇
  • Nginx的优化及防盗链
  • 论文笔记:A Simple Framework for Contrastive Learning of Visual Representations
  • 第5章 if语句
  • C#使用异步的几种方法对比示例
  • 11. 图的入门
  • Web Service(三)—— SOAP学习
  • Linux进程层次分析
  • 【SWAT水文模型】ArcSWAT输入准备
  • 学会SpringBoot的第一天(超详细)
  • 案例01-tlias智能学习辅助系统02-文件上传
  • 基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)
  • 详解为什么C++ 虚拟成员函数模板不被允许
  • mybatis配置文件详解
  • 记录-有意思的气泡 Loading 效果
  • Redis入门学习笔记【二】Redis缓存
  • OSCP-Sirol(docker容器到宿主机)