J反射机制
反射机制常用的class
Java.lang.Class
Java.lang.reflect.Constructor
Java.lang.reflect.Field
Java.lang.reflect.Method
Java.lang.reflect.Modifer
//取得class对象
Class userklass = Class.forName(“”);
//获取字段
Field[] array = userklass.getFields();//公有字段
Userklass.getDeclaredFields();// 获得所有字段
User.getField(“”) //获得字段调用
Object obj = userKlass.getConstructor.nextInstance//获取对象
反射优点: 动态访问 对象的字段 方法
缺点: 效率比较低
JMM
JMM模型用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果,JMM规范了Java虚拟机与计算机内存是如何协同工作的:规定了一个线程如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量
JMM 内存交互操作有8种:
lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。
HashMap 底层结构
HashMap 由数组+链表组成的,数组是HashMap的主体,链表则是主要为了解决哈希冲突而存在的
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap 是无序的,即不会记录插入的顺序。
HashMap 继承于AbstractMap,实现了 Map、Cloneable、java.io.Serializable 接口。
Hasmap初始容量 16 负载因子0.75, 自增长容量为原来的2倍,按2的幂次自增。
Concurrencymap 如何实现线程安全
Collections.synchronizedMap
HashTable
使用的是全局锁,把整个hash表都lock
Concurrecymap用的是局部锁
1.7 之前Concurrencymap本身维护了一个Segment的数组,每一个segment可以看做一个hashmap。 Segment 里定义了HashEntry 和 HashMap里的HashEntry一样是用来存放数据的。在put的时候 通过key找到对应的segment,并且在执行Put方法的时候会把这个segement加锁,而不影响其他的segement。 因为Segement这个class继承了ReentrantLock的trylock()方法来尝试获取锁,如果能锁上就直接插入数值,如果数据已经被锁了,则尝试 然后等待。
1.8之后, Concurrencymap用node 替代了HashEntry来存储数据,并且增加了常量TREEIFY_THRESHOLD 用于判断是否需要将链表转换为红黑树的阈值。数组长度大于64,链表长度大于8就转变成红黑树。红黑树节点长度小于6退回链表
上锁的过程是使用了synchronized替代了ReentrantLock。 在执行put操作的时候,用synchronized 互斥锁,给node资源上锁。 Node有validate,使其保证内存可见性,使得这个值保持更新。
Mysql 用b+tree的原因是,因为InnoDB的最小存储单位页,它的大小4,8,16K,根据设置,Btree的数据结构是可在一次IO读取 取得尽量多的数据,而不像AVLtree 或者红黑树,浪费资源。B+tree 相对Btree, 它的所有的数据都存在根节点,且每个根节点有双向链表相连可以范围检索。同时因为只在根节点存储数据,那么单次IO的在固定大小的情况下,取得的数据量更多,相对的IO次数,比BTREE会减少。
索引算法Btree 和 B+ tree 的区别
建立索引的原则
表的主键、外键必须有索引;主键具有唯一性,索引值也是有唯一的,查询时可以快速定位到数据行;外键一般关联的是另一个表的主键,所以在多表查询时也可以快速定位
记录数超过300行的表应该有索引;如果没有索引,需要把表遍历一遍,会严重影响数据库的性能
经常与其他表进行连接的表,在连接字段上应该建立索引
唯一性太差的字段不适合建立索引,并不能提升查询速度,反而会变慢
更新太频繁地字段不适合创建索引;在表中进行增、删、改、查时,索引也会有响应操作产生;字段更新的过于频繁,会导致对于系统资源的过多占用
经常出现在 where 子句中的字段,特别是大表的字段,应该建立索引
索引应该建在选择性高的字段上;如果很少的字段拥有相同值,即有很多独特之,则选择性很高。离散度低的,数据命中次数多,造成过多的IO操作,影响效率。
索引应该建在小字段上,对于大的文本字段甚至超长字段,不要建索引
Mysql性能优化策略
Explain语法:explain select … from … [where ...]
例如:explain select * from news;
输出:
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
4、type:这列最重要,显示了连接使用了哪种类别,有无使用索引,是使用Explain命令分析性能瓶颈的关键项之一。
结果值从好到坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到range级别,最好能达到ref,否则就可能会出现性能问题。
缓存 三种读写方式(读写数据库一致性)
1. Cache aside (旁路缓存)
查询:应用程序先去cache中读取数据,如果可以命中,则直接返回;如果没有命中,则去数据库中查询,成功后存入缓存。
更新:应用程序先去更新数据库,成功后再删除缓存
2.Read /write through (读写穿透)
存储服务收到业务应用的写请求时,会首先查 cache,如果数据在 cache 中不存在,则只更新 DB,如果数据在 cache 中存在,则先更新 cache,然后更新 DB。而存储服务收到读请求时,如果命中 cache 直接返回,否则先从 DB 加载,回种到 cache 后返回响应。
3.write behind caching (异步缓存写入)
在该模式下,更新数据时只更新缓存,不直接更新DB,通过异步的方式将缓存结果批量的或合并后再更新到DB。这种方式的特点是效率非常高,但不是强一致,甚至会丢失数据,适用于访问量、点赞数等对于性能要求高,但一致性要求不高的场景。
ES的知识点 elasticsearch 倒排索引原理
elasticsearch 倒排索引原理 - 知乎
ES比Mysql查询效率高的原因:
相对于mysql的倒排索引,es多了一个包含了索引前缀的trie树数据结构,在检索的时候可以根据trie树更快的找到索引结果。Term -> term dictionary
NLP项目回忆
执行流程是: 数据导入,分词,特征提取(有一个词库,提取相关),分类(用了SVM 和 navie Bays(朴素贝叶斯)算法模型)。
Spring与Springboot相关
传统Spring框架存在的弊端:
Spring事物管理,MVC,启用第三方库都需要XML或Java进行显示配置,配置过重
写配置挤占了实际写应用的逻辑的时间
项目依赖管理,要考虑用那些库,还要知道哪些版本和库不会有冲突,影响开发效率
SpringBoot的优势:
自动配置:针对很多Spring常见的应用功能,SpringBoot能自动提供相关配置
起步依赖:告诉SpringBoot需要什么功能,它就能引入需要的库
CLI命令行界面:通过SpringBootCLI,借此你只需写代码就能完成完整的应用程序,无须传统项目构建
Spring 相关
@autowire 和@Resource的区别
Spring解决循环依赖的方法
Spring事务@Transitional失效的 8 大原因
synchronized 和 voliate 的区别
volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住
常见Mysql的慢查询优化方式
- 开启慢查询日志
- 直接分析mysql慢查询日志 ,利用explain关键字可以模拟优化器执行SQL查询语句,来分析sql慢查询语句
- 分析sql语句
- 查看索引是不是没起到作用,例如也有like ‘%abc’或者隐式的变量类型转换。
- 优化表结构,如果字段太多,也会影响查询效率。
- 将一个大的查询分解为多个小查询是很有必要的。
- 优化具体的sql语句
- 优化limit分页
例子:select id,title from collect limit 90000,10; ->
先查询出主键id值
select id,title from collect where id>=(select id from collect order by id limit 90000,1) limit 10;
原理:先查询出90000条数据对应的主键id的值,然后直接通过该id的值直接查询该id后面的数据。
Spring中Bean的作用域
默认情况下,Bean在Spring容器中是单例的(singleton),可以通过@Scope注解或者配置文件中的scope属性设置Bean的作用域
①singleton:在Spring容器中仅存在一个这个Bean的实例,即一个Bean定义对应一个对象实例。
②prototype:一个bean定义对应多个对象实例。每次调用StringBeanUtil.getBean()时,都会执行new操作,返回一个新的Bean实例。
③request:每次Http请求都会创建一个新的Bean,该作用域仅在当前HTTP Request内有效。
④session:同一个Http Session共享一个Bean,不同Http Session使用不同的Bean。该作用域仅在当前 HTTP Session 内有效。
⑤ global session :在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。
MySql的事务隔离级别
三种并发情况: 脏读,不可重复读,幻读
脏读: 读取到 未提交的数据
不可重复读: 一个事物读取到提交过的数据,
幻读: 一个事物读取到 另一个事物插入的数据
对应四种隔离级别
未提交读(read-uncommited)
提交读 (read-commited)
可重复读(read-repeated)
串行化 (serializable)
Redis持久化
https://www.cnblogs.com/itdragon/p/7906481.html
AOF
RDB 内存快照(默认开启)
触发条件:
1 在指定的时间间隔内,执行指定次数的写操作
2 执行save(阻塞, 只管保存快照,其他的等待) 或者是bgsave (异步)命令
3 执行flushall 命令,清空数据库所有数据,意义不大。
4 执行shutdown 命令,保证服务器正常关闭且不丢失任何数据,意义...也不大。
通过RDB文件恢复数据:
将dump.rdb 文件拷贝到redis的安装目录的bin目录下,重启redis服务即可。在实际开发中,一般会考虑到物理机硬盘损坏情况,选择备份dump.rdb 。可以从下面的操作演示中可以体会到。
RDB 的优缺点
优点:
1 适合大规模的数据恢复。
2 如果业务对数据完整性和一致性要求不高,RDB是很好的选择。
缺点:
1 数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。
2 备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍哦),最后再将临时文件替换之前的备份文件。
所以Redis 的持久化和数据的恢复要选择在夜深人静的时候执行是比较合理的。
Mysql死锁发生条件
事物占用资源的同时,请求另一个被占用的资源,就发生死锁。
JAVA 死锁的四个必要条件
互斥条件:一个资源同时只能被一个线程所使用.
请求与保持条件: 例如请求第二把锁的时候, 保持自身的第一把锁不去释放.
不剥夺条件: 进程已获得的资源(例如已经获得的锁),没有外界的力量来去剥夺这把锁.
循环等待条件: 两个线程时, 是你等我释放锁, 我等你释放锁. 多个线程时, 是头尾相接的等待.
JVM 内部
内部结构是分为线程共享堆(GC),线程私有程序计数器,虚拟机栈,本地方法栈,曾经有方法区,后来变成meta space放到内存