问题收集

185 阅读12分钟

HashTable线程安全,但是

currenhashmap的线程安全实现原理

ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候

其他安全容器的实现原理

乐观锁(线程不阻塞,使用版本号或者cas实现)和悲观锁(线程阻塞)

mysql的乐观锁和悲观锁

runable和callable的区别

倒排索引

threadloacl的实现原理

mysql 的update过程

redis的hash实现

ribbon的负载均衡的实现原理

eruka为


事务失效的情况:

www.cnblogs.com/javastack/p…

synchroniz的缺陷:

缺少了获取锁和释放锁的可操作性,可中断、超时获取锁,且他为独占式在高并发场景下性能大大折扣

AQS

1、AQS是依赖内部的同步队列实现

2、如果当前线程竞争锁失败,那么AQS会把当前线程以及等待状态封装成一个Node节点加入到同步队列中,同时阻塞该线程

3、当同步状态释放时,会把首节点唤醒,使其再次尝试获取同步状态。

特点:

1、AQS队列内部维护的是一个双向链表,这种结构每个数据都有两个指针,分别指向直接的的前驱节点和后继节点,当线程抢占锁失败时候,会封装成Node加入到AQS中去

2、一个节点:他保存这线程的引用ThreadId,状态(watiStatus),前驱结点(pre),后继节点(next)

节点状态waitStatus,常量有:cancelled,signal,condition,propagate,0

cancelled(1):表示当前节点已取消调度。当timeout或者中断情况下,会触发变更为此状态,进入该状态后的节点不再变化 signal(-1),表示当前节点释放锁的时候,需要唤醒下一个节点。或者说后继节点在等待当前节点唤醒,后继节点入队时候,会将前驱节点更新给signal condition(-2),当其他线程调用了condition的signal方法后,condition状态的节点会从等待队列转移到同步队列中,等待获取同步锁。 propagate(-3),共享模式下,前驱节点不仅会唤醒其后继节点,同时也可能唤醒后继的后继节点。 0 ,新节点入队时候的默认状态。

addWaiter添加节点:

此方法用于将Node加入队尾,核心就是通过CAS自旋的方式设置尾结点 另一个线程cas失败,则进入下次循环,通过cas操作将node添加到队尾。

blog.csdn.net/a718515028/…

reentanlock的实现原理

其实从上面这写方法的介绍,我们都能大概梳理出ReentrantLock的处理逻辑,其内部定义了三个重要的静态内部类,Sync,NonFairSync,FairSync。Sync作为ReentrantLock中公用的同步组件,继承了AQS(要利用AQS复杂的顶层逻辑嘛,线程排队,阻塞,唤醒等等);NonFairSync和FairSync则都继承Sync,调用Sync的公用逻辑,然后再在各自内部完成自己特定的逻辑(公平或非公平)。

lock 上锁

unlock

condition 唤醒操作

共享锁和独占锁

独占锁:指该锁一次只能被一个线程所持有。对ReentrantLock和Synchronized而言都是独占锁

ReentrantReadWriteLock其读锁是共享,其写锁是独占

sychronize:synchronize有三种锁(锁的膨胀),会根据情况升级锁,最初是偏向锁,会升级到轻量级锁和重量级锁 偏向锁: 有竞争

轻量级锁 cas

重量级锁: 通过monitor每个对象都与monitor关联,同步时,修改相关标志位,但是修改标志为的指令是调用操作系统的方法实现,被阻塞的线程,需要挂起,等待调度,这个过程,用户态和内核态需要来回切换,消耗性能


多线程的使用场景

1、压力测试,问题排查

2、查询数据

3、框架使用多线程

线程池的类型

单线程线程池

fixedpool线程池

cach线程池

定时任务线程池

cyclibarral,countdownlatch

线程池的参数有哪些?

runable和callable的区别


arrylist和linklist的底层添加,删除实现

add:检查是否有空间添加一个数据,

add("铁扇", 0); //将数组中的元素各自往后移动一位,再将“铁扇”放到第一个位置上;

get,根据下标定位

remove(int index) 将index后面所有的元素往前移一位

总结:arrylist在删除和添加操作的时候,

linklist: 数据存储是基于双向链表实现的。 插入数据很快

删除数据很快

获取数据很慢,需要从Head节点进行查找。

遍历数据很慢,每次获取数据都需要从头开始

但是删除和添加快


hashmap put数据的过程

1、p 当前散列元素

2、n 散列表数值的长度

3、i 路由寻址结果

在第一次插入数据的时候:

创建散列表(延迟初始化)

通过hash $ 表长 确认位置

如果hash后的位置的value组个比较,没有相同,就添加到末尾,否则替换,返回旧值,如果有这个值,就不操作

重点是equal和hash,判断一个值或者是链表

hash的过程:

1、对字符串值转换为32位的二级制数,在原来的基础上右移动16位,与原来的二级制异或,得到hashcode,这样是为了让高16位可以参与到取模(L-1)0

(n - 1) & hash

在有put值后,才会创建空间,扩容后,L只是在最高位

默认map的数组长度16

链表大于8变为红黑树

扩容的方法:条件 数组容量(2^n) * 0.75

size是每插入一个新的hashcode size 加一 如果 数组容量(2^n) * 0.75 》 size,会进行扩容;扩容后数组大小为当前的 2 倍。


jvm调优过程

问题排查: 场景:服务的调用比较慢,或者失败。

查看监控器:服务是否已经死了,如果死了,查看cpu是否过高

tail -100f test.log 实时监控100行日志

service servicename status 查看服务状态

ps指令查看当前的服务

netstat -tunlp |grep 端口号 ( -t (tcp) 仅显示tcp相关选项 -u (udp)仅显示udp相关选项 -n 拒绝显示别名,能显示数字的全部转化为数字 -l 仅列出在Listen(监听)的服务状态 -p 显示建立相关链接的程序名 )

jstack -l 4089 >1.txt 查看栈信息

jmap -dump:file=a.dump


springboot的自动装配

执行run方法会刷新容器,也就是解释注解

根据springbootconfiguration

包扫描 enableautoconfigraion

import类

selectimport

加载spring.factory的配置文件,加载需要自动装配的类

总结:spring依靠mian方法启动在其中会调用springapplication。mian方法在run 方法中有刷新容器的功能reflex方法,然后解析注解,会解析到springapplication,这个配置类有自动装配注解的功能,在这个方法里面有加载spring。factory的功能,他会根据使用到的注解,将这些配置到加载到容器中,实现自动装配


阻塞非阻塞,同步异步

阻塞需要等待有返回结果,在这期间,线程是挂起的(非阻塞不是)线程问题

同步:线程A执行到某个步骤是需要线程B的执行结果(异步则不需要等待)业务


ps 命令用来列出系统中 当前正在运行 的那些进程

top指令查看服务的cpu使用情况

jmap id 查看jvm的内存使用情况

jmap -dump:file=a.dump dump出文件

查看内存泄漏的情况(都存放在老年代)大量的

1、静态集合,因为里面的引用一致不能释放,但是是短生命周期的

2、各种连接,如数据库连接、网络连接和IO连接等 如果在访问数据库的过程中,对Connection、Statement或ResultSet不显性地关闭,将会造成大量的对象无法被回收

3、队列中的值无法被消耗



@enabledubbo,开启dubbo @sevice暴露service服务

dubbo的注册信息,最终会封装为bean,所以可以使用xml,yaml,@configration来实现

dubbo服务暴露:

1、检查dubbo服务配置信息是否正确(服务配置信息错误的时候,会报错),同时注册registconfig注册中心的地址和protoconfig(使用list封装,是因为可以注册到多个注册中心),协议dubbo,redis。。。协议类型,存放在configmanager里面

serviceconfig。doexport()--doexporurl(如果没有服务暴露,执行这个方法

2、将注册中心的信息,封装成url,放在registyuurls中

3、本地的url拼接

4、然后将服务的所有连接,对注册中心执行一个for循环,将dubbo服务链接注册到每个注册中心上

将每种注册中心的链接,都封装为dubbo的标准格式

5、开启nettyerver

6、netty服务开启

将dubbo服务的链接组装好,发送给每个注册中心,dubbo提供者,完成url的解析

开启nettyserver,开启netty链接

暴露本地协议injvm://127.0.0.1

如果是registry://127.0.0.1,实现远程暴露

),以url的形式暴露(provider,)

3、读取配置文件信息,组装成这样的格式:支持多种注册中心,标准化的暴露格式是register:地址:/register=注册中心的类型

4、protoconfig代表一个dubbo服务,每个服务都会到注册中心上面进行注册

5、启动一个dubbo服务就会有一个服务的地址,里面

6、通过dubbo的spi机制对dubbo进一步封装

7、本地服务暴露,

8、判断是否是registey开头的url,如果是,就是远程暴露,否则为本地暴露

9、创建nettyservice,openservice,一个服务里面有多个接口,但是他们共用一个nettyservice,使用双重检查锁判断,然后执行netty代码

10‘、将服务注册的注册中心

1、mysql库的数据类型,底层原理 INT;FLOAT、DOUBLE、CHAR、VARCHAR、TINY TEXT、TEXT、BLOB、Date、DateTime、TimeStamp

2、数据库索引建立需要考虑什么问题、索引的使用选择 索引的区分度;字段的长度选择短的;索引为频繁使用的字段,需要排序,分组的字段

44.你们数据库库用的什么引擎? innodb ISAM

45.说一下数据库的主从原理

slaver上的io线程请求获取

Slave 上面的IO线程连接上 Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;

46.Innodb支持hash索引吗? 不支持

47.说一下explain命令里面,索引类型

const、eq_reg、ref、range、 index、ALL

1、Master 接收到来自 Slave 的 IO 线程的请求后,通过负责复制的 IO 线程根据请求信息读取指定日志指定位置之后的日志信息,返回给 Slave 端的 IO 线程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息在 Master 端的 Binary Log 文件的名称以及在 Binary Log 中的位置;

2、将接收到的日志内容依次写入到 Slave 端的Relay Log文件

3、Slave 的 SQL 线程检测到 Relay Log 中新增加了内容后,会马上解析该 Log 文件中的内容成为在 Master 端真实执行时候的那些可

31、数据库时间字段有哪几种,它们有什么区别: date:年月日;time:时分秒;datetime 年月日 时分秒 ;

32、数据库如果存储比较大的文表,供选择的字符有哪些,有什么区别

tinytext 、text 、longtext

42.动态spl的标签有哪些 if choose (when, otherwise) trim (where, set) foreach

43.枚举类和mapper.Xml可以映射吗?

29 redis的缓存雪崩,发生雪崩的原理,解决办法

30、redis缓存穿透

3、缓存穿透及解决方案

key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源

使用布隆过滤器、使用double lock,没有数据,就预设一个数据

36、java的单例实现方式 饿汉式、懒汉式、静态内部类、枚举

41、单例模式的作用 使用单例模式好处在于可以节省内存,节约资源,对于一般频繁创建和销毁对象的可以使用单例模式

缺点:有的为了节省资源创建单例模式,可能会导致共享连接池的对象程序过多,出现连接池溢出等问题。

     可能会造成一些开发混淆,因为单例模式的不能进行自己实例化。

1.单例的缺点 就是不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。

2.单例模式的构造函数是静态的,所以在继承单例时,出现问题,不能被子类继承

22、dubbo是如何运作的,dubbo的运行原理 结构,生产者,消费者,监控器,注册中心

24、dubbo调用流程

1、服务容器Container 负责启动加载运行服务提供者Provider。根据Provider配置的文件根据协议发布服务 , 完成服务的初始化.

2、Provider在启动时,根据配置中的Registry地址连接Registry,将Provider的服务信息发布到Registry,在Registry注册自己提供的服务。

3、Consumer在启动时,根据消费者XML配置文件中的服务引用信息,连接到Registry,向Registry订阅自己所需的服务。

4、Registry根据服务订阅关系,返回Provider地址列表给Consumer,如果有变更,Registry会推送最新的服务地址信息给Consumer。

5、Consumer调用远程服务时,会根据路由策略,先从缓存的Provider地址列表中选择一台进行,跨进程调用服务,假如调用失败,再重新选另一台调用。

6、服务Provider和Consumer,会在内存中记录调用次数和调用时间,每分钟发送一次统计数据到Monitor。

34、v-show跟v-if的区别(针对会前端的人员) 35、v-bind的作用(针对会前端的人员) 37、如何安装element-ui(针对会前端的人员) 38、页面渲染(针对会前端的人员) 39、jquey遍历数组的方式