随笔

多线程

  • 死锁的条件,如何打破,如何避免
    四个条件:
    1.互斥 同一资源在同一时间只能由一个进程占用,其他进程只能等待释放资源。
    2.占用且请求 进程独占资源A同时申请请求资源B
    3.不可剥夺 进程在独占资源时不可被其他进程强制夺走
    4.循环等待 进程间形成循环等待环
    打破死锁从以上条件入手:
    互斥是资源固有的特性,不可打破。
    破坏占用且请求:进程在请求资源时将所有需要独占的资源一次性占用。或者自身不占用资源只是请求新的资源。
    破坏不可剥夺:进程在请求其他进程占用的资源时,等待期间释放自身占用的资源。
    破坏循环等待:将所有资源进行顺序编号,资源稀缺的给大的编号,进程只能先请求小的资源进而申请大的。
    避免死锁:
    不限制每个进程申请资源的命令,而是动态的在进程申请资源命令时动态的进行检查,通过检查结果来是否分配资源。实现为:银行家算法。具体算法不详诉。

  • JMM JVM的共享内存模型

  • 如何创建线程池,队列都有哪些?拒绝策略都有哪些?任务过多时都是如何处理的
    创建线程池四种方式
    1.newFiexedThreadPool() 创建固定数量线程的线程池。
    2.newCachedThreadPool()创建可缓存的线程池
    3.newSingleThreadExecutor()创建单线程的executor
    4.newScheduledThreadPool()创建支持定时及周期性执行的线程池
    队列有三种:
    1.有界缓冲队列ArrayBlockingQueue 任务过多时,超过corePoolSize则进入定长队列,队列满时启动新线程直到maximumPoolSizes,执行拒绝策略
    2.无界缓冲队列LinkedBlockingQueue,超过corePoolSize则进入无界队列,maximumPoolSizes无效,这也是为何阿里规约限制使用Executor的原因。
    3.无缓冲等待队列SynchronousQueue,不存储直接交给消费者,超过corePoolSize直接新启动线程,达到maximumPoolSizes则等待。
    拒绝策略有四种:
    1.丢失抛异常AbortPolicy
    2.丢弃不抛异常DiscardPolicy
    3.丢弃最前边的任务执行最新的任务DiscardOldestPolicy
    4.由调用线程执行该任务CallerRunsPolicy

  • 线程生命周期
    新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)五种状态
    当创建Thread类的一个实例(对象)时 t=new Thread(),此线程进入新建状态(未被启动)。
    t.start().线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源
    t.run()运行

  • synchronized原理
    由jvm字节码中可以看到ACC_SYNCHRONIZED,对同步块使用了monitorenter和monitorexit指令,隐式的实现了lock,unlock。

  • jdk对synchronized做了哪些优化
    jdk1.6对锁做了优化,在对象头中包含了轻量锁,重量锁,偏向锁。
    synchronized使用的锁对象是存储在Java对象头里。它是轻量级锁和偏向锁的关键,偏向线程ID指向自己
    https://www.cnblogs.com/wuzhenzhao/p/10250801.html

  • ReentrantLock
    ReentrantLock是可重入的独占锁。比起synchronized功能更加丰富,支持公平锁实现,支持中断响应以及限时等待等等。可以配合一个或多个Condition条件方便的实现等待通知机制。

  • CAS、ABA问题
    CAS乐观锁操作,Compare and Swap 这是一个重量锁的实现。
    ABA A改为B又改为A,这种问题使用版本号控制解决。

  • J.U.C java.util.concurrent。
    CompareAndSet 利用Unsafe类的JNI方法实现CAS,无锁算法
    https://segmentfault.com/a/1190000015558984

基础

  • ArrayList和LinkedList
    ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表结构。
    modCount是ArrayList中的一个成员变量。
  • 什么是fail—fast?
    快速失效系统,先考虑异常情况,一旦发现异常立马终止。业务设计接口检测抛出异常就是这个东西。还有一种是指Java集合的一种错误检测机制,当多个线程对部分集合进行结构上的改变的操作时,有可能会产生fail-fast机制,这个时候就会抛出ConcurrentModificationException。
  • HashMap的put、扩容原理,1.7和1.8的数据结构
put

扩容

1.7 hashmap 数组+链表
1.8 数组+链表+红黑树 链表长度大于8转为红黑树


image.png

image.png

image.png

为何链表长度为8,hashcode之后的频率遵循泊松分布,泊松分布对照表中链表为8的概率非常小。

  • HashMap并发问题
    主要出在扩容阶段,当两个线程同时resize时链表会成环状链表,当调用get时会陷入死循环。
  • TCP粘包,为什么出现,如何解决?
    tcp为提高性能,发送端会将需要发送的数据发送到缓冲区,等待缓冲区满了之后,再将缓冲中的数据发送到接收方。同理,接收方也有缓冲区这样的机制,来接收数据。
    约定数据包长度这样可以清晰的获取到我们需要的数据;使用分隔符;每个数据包的开头利用2个或者4个字节填充整个数据包的长度
  • TCP如何实现消息可靠性、滑动窗口
    TCP确认重传机制,滑动窗口为TCP不是每一段报文都进行ACK,如果接收方期望的报文一直没来,其他的报文则会放入滑动窗口缓冲区。
  • TCP三次握手四次挥手
    1.客户端首先要SYN=1,表示要创建连接,
    2.服务端接收到后,要告诉客户端:我接受到了!所以加个ACK=1,就变成了ACK=1,SYN=1
    3.理论上这时就创建连接成功了,但是要防止一个意外(重试多次建立连接问题),所以客户端要再发一个消息给服务端确认一下,这时只需要ACK=1就行了。
    在四次挥手时,
    1.首先客户端请求关闭客户端到服务端方向的连接,这时客户端就要发送一个FIN=1,表示要关闭一个方向的连接
    2.服务端接收到后是需要确认一下的,所以返回了一个ACK=1
    3.这时只关闭了一个方向,另一个方向也需要关闭,所以服务端也向客户端发了一个FIN=1 ACK=1
    4.客户端接收到后发送ACK=1,表示接受成功
  • 事务的隔离级别、mysql和oracle默认是什么,都解决了什么问题
    read uncommitted 未提交读 所有事务都可以看到没有提交事务的数据。
    read committed 提交读 事务成功提交后才可以被查询到。
    repeatable 重复读 同一个事务多个实例读取数据时,可能将未提交的记录查询出来,而出现幻读。mysql默认级别
    Serializable可串行化 强制的进行排序,在每个读读数据行上添加共享锁。会导致大量超时现象和锁竞争。
  • 事务的特性
    ACID-原子性 一致性 隔离性 持久性
  • 快照读和当前读
    快照读 即读取数据的可见版本,数据可能是历史数据。主要通过MVCC(多版本控制)和undo log 来实现,优势是不加锁,并发性高。缺点是不是实时数据
    当前读 是通过加record lock(记录锁)和gap lock(间隙锁)来实现的 (select ... for update)
    InnoDB为每行记录添加了一个事务ID,每当修改数据时,将当事务ID写入。
  • 乐观锁、悲观锁、间隙锁、行锁、表锁的使用场景
    乐观锁 读的时候不加锁,只有在更新的时候判断版本号进行更新
    悲观锁 读的时候就加上锁
    间隙锁 当我们用范围条件检索数据,并请求共享或排他锁时,InnoDB会给符合范围条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”。InnoDB也会对这个“间隙”加锁
    行锁 锁颗粒度为行级
    表锁 表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)
    B数 B+树、聚簇索引和非聚簇索引
    B数为多叉数,和平衡二叉树不同的是搜索路径不止两条,同样遵循左小右大原则
    B+树 B+的搜索与B-树也基本相同,区别是B+树只有达到叶子结点才命中(B-树可以在
    非叶子结点命中)
    B+的特性:
    1.所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好
    是有序的;
    2.不可能在非叶子结点命中;
    3.非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储
    (关键字)数据的数据层;
    4.更适合文件索引系统;
    B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率
    从1/2提高到2/3;
    聚簇索引 innodb中根据主键生成B+树,叶子节点存储的是行记录数据,也将聚集索引的叶子节点称为数据页。
    非聚簇索引  在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找。辅助索引叶子节点存储的不再是行的物理位置,而是主键值
     MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构
  • mvcc多版本并发控制
    在每一行数据会隐藏式创建两个列。行创建时的版本号和删除时的版本号。
    每行数据都存在一个版本,每次数据更新时都更新该版本。修改时Copy出当前版本随意修改,各个事务之间无干扰。保存时比较版本号,如果成功(commit),则覆盖原记录;失败则放弃copy(rollback)
  • redolog、undolog、binlog
    redolog 重做日志 是每个数据在更新时将更新记录到redo日志中,定时刷入磁盘。
    和undolo同属于事务日志,不同的是redo是前滚日志。保证了事务的持久性
    undolog 回滚日志,保存了事务数据更新前一个数据,保证了事务的原子性。
    binlog 归档日志,主要用于主从复制,记录了相关sql记录。
  • 索引失效的场景
    1.有 or 的
    2.like 前缀%
    3.字符串值为数字,不加单引号的
    4.联合索引不按顺序
    5.不要对索引列进行聚合函数操作
  • Redis数据类型,底层数据结构
    string hash list set zset bitmap hyteloglog geo stream
  • 缓存穿透、缓存击穿 缓存雪崩
    查询一个不存在的key ,缓存null,布隆过滤器
    key 过期后大量的请求打在db上,db查询加锁及限流
    缓存雪崩 大量的key同一时间过期,随机时间
  • mysql和redis 一致性问题
    给缓存设置合理的过期时间,或者进行补偿。或者使用阿里开源canal ,对mysql的binlog进行订阅,对redis在进行处理。

spring

  • IOC和AOP的理解及原理
    IOC就是典型的工厂模式,由sessionFactory去注入实例。通过IOC容器可以将依赖的对象创建等交给spring去处理
    AOP就是面向切面编程,分离关注点。动态代理和静态织入
  • Bean的生命周期
    大概分为9步:
    1,实例化bean对象
    2.设置对象属性
    3.如果bean实现了beanNameAware则将会将bean的ID进行传递
    4.如果bean实现了beanfatoryAware则传递工厂
    5.调用bean的前置处理器
    6,bean的初始化
    7.调用bean的后置处理器
    8.使用bean
    9.销毁bean
  • 自动注入方式有哪些,两个注解的区别
    @Autowired 基于bytype的注入,默认对象必须是存在的,是spring提供的注解
    @Resource 基于byname的注入,默认对象可为null 是J2EE提供的注解
    @Inject 先基于name查找没有则使用类型查找
  • MVC流程


    image.png
  • 分布式事务怎么做的
    1.XA saga TCC seata
    XA 两阶段提交 性能有问题 并不是所有资源都支持XA协议
    saga 基于应用共享事务记录执行轨迹;然后通过异步重试确保交易最终一致
    TCC 的特点在于业务资源检查与加锁,一阶段进行校验,资源锁定,如果第一阶段都成功,二阶段对锁定资源进行交易逻辑,否则,对锁定资源进行释放。应用实施成本较高。
    Seata架构的亮点主要有几个:
    应用层基于SQL解析实现了自动补偿,从而最大程度的降低业务侵入性;
    将分布式事务中TC(事务协调者)独立部署,负责事务的注册、回滚;
    通过全局锁实现了写隔离与读隔离。
  • CAP、BASE理论
    CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。zk是CP,eurka是AP.
    BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。
  • 高并发之服务降级和服务熔断
    牺牲局部,保全整体的措施
  • 令牌桶、漏桶、滑动窗口算法
    控制数据注入到网络的速率,平滑网络上的突发流量
  • 分布式id如何生成
    1.主键自增
    2.redis
    3.雪花算法
    4,leaf 缓存一个号段 双buffer

JVM

  • 共享内存区
    程序计数器
    Java虚拟机栈
    本地方法栈
    Java堆
    方法区
  • 几种OOM


    image.png
  • 类加载机制
    JVM类加载机制分为五个部分:加载,验证,准备,解析,初始化
  • 双亲委派机制
    如果一个类加载器收到了类加载器的请求.它首先不会自己去尝试加载这个类.而是把这个请求委派给父加载器去完成.每个层次的类加载器都是如此.因此所有的加载请求最终都会传送到Bootstrap类加载器(启动类加载器)中.只有父类加载反馈自己无法加载这个请求(它的搜索范围中没有找到所需的类)时.子加载器才会尝试自己去加载。
    双亲委派模型的优点:java类随着它的加载器一起具备了一种带有优先级的层次关系.
  • 新生代默认多少次晋升老年代
    MaxTenuringThreshold 默认为15,并不是指15次gc晋升,有动态阈值调整

你可能感兴趣的:(随笔)