gc策略 cms g1 和 zgc
1. 初始标记(CMS initial mark)
2. 并发标记(CMS concurrent mark)
3. 重新标记(CMS remark)
4. 并发清除(CMS concurrent sweep)
G1能充分利用多CPU,多核的硬件优势来缩短Stop—The—World停顿的时间,部分其它收集器原本需要停顿用户线程执行的GC动作,
G1依然可以通过并发的方式让用户线程继续执行。
并行 指用户线程与垃圾收集线程同时执行(但不一定是并行的,可能会交替执行);
用户程序在继续运行,而垃圾收集程序线程运行于另一个CPU上
zgc 缩短时长的策略几乎都是从串行改为并行
做了哪些工作来提高查询的速度 查询的并发数
单个reqeust 对CPU消耗越高,外部系统接口、IO影响速度越慢,系统吞吐能力越低,反之越高。
2.1增加并发数1.比如增加tomcat并发的线程数,开喝服务器性能匹配的线程数,可以更多满足服务请求。
2.增加数据库的连接数,预建立合适数量的TCP连接数
3.后端服务尽量无状态话,可以更好支持横向扩容,满足更大流量要求
4.调用链路上的各个系统和服务尽量不要单点,要从头到尾都是能力对等的,不能让其中某一点成为瓶颈。
5.RPC调用的尽量使用线程池,预先建立合适的连接数。
2.2减少平均响应时间
1.请求尽量越前结束,越好,这样压力就不要穿透到后面的系统上,可以在各个层上加上缓存
2.流量消峰。放行适当的流量,处理不了的请求直接返回错误或者其他提示。和水坝道理很类似
3.减少调用链
4.优化程序
5.减少网络开销,适当使用长连接
6.优化数据库,建立索引
spring生成对象默认是单例的。通过scope属性可以更改为多例
Spring核心机制:依赖注入 反射
控制反转还是依赖注入,他们都可以这样理解:当某个Java实例(调用者)需要另一个Java实例(被调用者)时,在传统的程序设计过程中,通常有调用者来创建被调用者的实例。但是在依赖注入/控制反转模式下,创建被调用者的工作不再是有调用者来完成,而是由Spring容器来完成,然后注入调用者。
对于Spring而言,Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现都是透明的。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。
依赖注入通常有如下两种:
1、
设置注入:IoC容器使用属性的setter方法来注入被依赖的实例。
2、
构造注入:IoC容器使用构造器来注入被依赖的实例。
一致性模型数据的一致性模型可以分成以下 3 类:
强一致性:数据更新成功后,任意时刻所有副本中的数据都是一致的,一般采用同步的方式实现。
弱一致性:数据更新成功后,系统不承诺立即可以读到最新写入的值,也不承诺具体多久之后可以读到。
最终一致性:弱一致性的一种形式,数据更新成功后,系统不承诺立即可以返回最新写入的值,但是保证最终会返回上一次更新操作的值。
yncronized 与 lock 区别
下,你对synchronized是不是了解的很清晰了呢。接下来我们再聊一聊Lock。
Lock:Lock实现和synchronized不一样,后者是一种悲观锁,它胆子很小,它很怕有人和它抢吃的,所以它每次吃东西前都把自己关起来。
而Lock呢底层其实是CAS乐观锁的体现,它无所谓,别人抢了它吃的,它重新去拿吃的就好啦,所以它很乐观。具体底层怎么实现,
可见性与原子性
可见性:一个线程对共享变量的修改,更够及时的被其他线程看到
原子性:即不可再分了,不能分为多步操作。比如赋值或者return。比如"a = 1;"和 "return a;"这样的操作都具有原子性。类似"a += b"这样的操作不具有原子性,在某些JVM中"a += b"可能要经过这样三个步骤:
① 取出a和b
② 计算a+b
③ 将计算结果写入内存
(1)Synchronized:保证可见性和原子性 Synchronized能够实现原子性和可见性;在Java内存模型中,synchronized规定,线程在加锁时,先清空工作内存→在主内存中拷贝最新变量的副本到工作内存→执行完代码→将更改后的共享变量的值刷新到主内存中→释放互斥锁。
(2)Volatile:保证可见性,但不保证操作的原子性
Synchronized和Volatile的比较
1)Synchronized保证内存可见性和操作的原子性
2)Volatile只能保证内存可见性
3)Volatile不需要加锁,比Synchronized更轻量级,并不会阻塞线程(volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。)
4)volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化(如编译器重排序的优化).
5)volatile是变量修饰符,仅能用于变量,而synchronized是一个方法或块的修饰符。
主线程等待所有线程都运行完后,再执行逻辑
,这个需求很普遍。比如,在处理数据时,为了效率期间,起了10个线程,分别处理一块数据,这样能缩短处理时间,10个线程都执行完后,继续进行下边的逻辑(有点map/reduce的意思)
。这里我们就需要用到java的线程同步类 CountDownLatch ,count down是计数的意思,latch是门闩的意思,合起来也就是计数的开关。我们看一下CountDownLatch的API。
个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await
方法会一直受阻塞。之后,会释放所有等待的线程,await
的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。
CountDownLatch 是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch
用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。用
N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N
次之前一直等待。
CountDownLatch 的一个有用特性是,它不要求调用 countDown
方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个 await。
codeReview 时候主要关注哪些方面?有那些固定的代码规范
比如 代码提交前一定要格式化 异常处理不能吃掉异常
集合初始化时,指定集合初始值大小 如hashmap 默认是16
java.util.Objects#equals (JDK7引入的工具类)
在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
mysql问题
如何提高sql语句的执行效率 有哪些方面需要注意 关联表少 建立索引 频率高 多字段组合 不要用模糊 计算 索引范围太小 分辨率 最左原则不知道 b+数
mysql的索引的原则 用在a、b两列上创建复合索引,应该把a放前面,还是把b放前面
mysql的两种存储引擎的索引存储机制
MyISAM索引实现 InnoDB索引实现
目前大部分数据库系统及文件系统都采用B-Tree或其变种B+Tree作为索引结构
B-树的特性:
1.关键字集合分布在整颗树中;
2.任何一个关键字出现且只出现在一个结点中;
3.搜索有可能在非叶子结点结束;
4.其搜索性能等价于在关键字全集内做一次二分查找;
5.自动层次控制
请简述项目中优化sql语句执行效率的方法,从哪些方面。sql语句性能如何分析?
(1)尽量选择较小的列
(2)将where中用的比较频繁的字段建立索引
(3)select子句中避免使用‘*’
(4)避免在索引列上使用计算,not,in和<>等操作
(5)当只需要一行数据的时候使用limit 1
(6)保证表单数据不超过200w,适时分割表
(7)针对查询较慢的语句,可以使用explain来分析该语句具体的执行情况
建索引的几大原则
(1) 最左前缀匹配原则
对于多列索引,总是从索引的最前面字段开始,接着往后,中间不能跳过。比如创建了多列索引(name,age,sex),会先匹配name字段,再匹配age字段,再匹配sex字段的,中间不能跳过。mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配。
(2) 尽量选择区分度高的列作为索引
(3) =和in可以乱序
比如a = 1 and b = 2 and c = 3,建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式。
(4) 索引列不能参与计算,保持列“干净”
比如:Flistid+1>‘2000000608201108010831508721‘。原因很简单,假如索引列参与计算的话,那每次检索时,都会先将索引计算一次,再做比较,显然成本太大。
(5) 尽量的扩展索引,不要新建索引。
mysql可以开启慢sql日志 通过查看日志文件来监控慢sql
也可以使用Druid连接池来监控SQL执行状态