1.*voliate它的的作用
1.线程的可见性:当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。
2.顺序一致性:禁止指令重排序。
2.*java当中有哪些集合类
一、Java中的集合主要分为四类 :
1、List列表:有序的,可重复的;
2、Queue队列:有序,可重复的;
3、Set集合:不可重复;
4、Map映射:无序,键唯一,值不唯一
3.*ArrayList和LinkList的区别
-
ArrayList 基于动态数组,查询效率高,因为要移动数据,所以插入和删除操作效率比较低。 循环删除时容易有问题。
-
LinkedList是基于链表的数据结构,因此新增、删除操作比较有优势。LinkedList 适用于头尾操作。 但查询效率低。
-
适用场景 随机访问多,使用ArrayList 多次增删改,使用LinkedList
4.*创建线程有几种方式
-
继承Thread类
-
实现Runnable接口
-
实现Callable接口 相对于Runnable接口,Callable接口可以有返回值,可以声明抛出异常。
-
使用线程池
5.***线程池的基本原理以及7个参数的作用,它的4个拒绝策略是什么
为什么使用线程池?
-
降低资源消耗。 可以重复利用已经创建的线程,降低创建和销毁造成的消耗。
-
提高响应速度。 可以直接复用线程池中已有的线程。
-
提高线程的可管理性 使用线程池能够统一分配、监控和优化。
7个参数
-
corePoolSize 核心线程数量,
-
maximumPoolSize 最大线程数量
-
keepAliveTime 线程空闲存活时间
-
unit 线程存活时间单位
-
workQueue 任务队列,用于存放已提交的任务
-
threadFactory,线程工厂
-
handler 拒绝策略
为什么使用阻塞队列? 避免线程池内部使用阻塞-唤醒机制。这样当从空队列获取或向满队列插入时会自动阻塞, 当队列状态变化时也会自动唤醒等待线程。
4个拒绝策略
1.AbortPolicy 直接拒绝抛出异常
2.DiscardPolicy 直接丢弃任务。
3.DiscardOldPolicy 丢弃阻塞队列中的任务,执行当前任务
4.CallerRunPolicy 让提交任务的线程来执行任务
6.*Reetrantlock和Synchvomze的区别
Synchronized可以修饰实例方法,静态方法,代码块。自动释放锁。
ReentrantLock一般需要try catch finally语句,在try中获取锁,在finally释放锁。需要手动释放锁
7.**cglib,jdk这两个动态代理的区别
8.**java当中有哪些垃圾回收算法
1.标记-清除算法(Mark and sweep)
● 这是最基本的垃圾回收算法之一。它分为两个阶段:标记阶段和清除阶段。 ● 标记阶段:从根对象出发,递归地标记所有可达对象,
● 清除阶段:遍历整个堆,清除未标记的对象。
● 缺点是会产生内存碎片,可能会影响后续对象的分配。
2.复制算法(copying):
● 这种算法将堆分为两个区域:From 区和 To 区。对象在 From 区中分配,当 From 区满时,会触发垃圾回收。
● 垃圾回收时,将所有存活的对象复制到 To 区,然后清除 From 区中的所有对象。
● 优点是不会产生内存碎片,但是需要额外的空间来存放To 区。
3.标记-整理算法(Mark and compact)
● 这种算法也是分为标记阶段和整理阶段。
● 标记阶段和标记-清除算法相同,但在整理阶段,它会将所有存活的对象向一端移动,然后清除掉移动后
● 的剩余空间。这样可以解决标记-清除算法的内存碎片问题。
4.分代算法(Generational)
● 这是目前主流的垃圾回收算法之一。它根据对象的存活周期将堆分为多个代(Generation),通常是新生代(Young Generation)、老年代(Old Generation)和永久代(Perm Generation)。
● 新生代中的对象通常存活时间较短,采用复制算法:老年代中的对象存活时间较长,采用标记-清除或标 记-整理算法。
5.并发标记-清除算法(Concurrent Mark and sweep)
● 这种算法在标记阶段和清除阶段尽量与应用程序同时进行,以减少垃圾回收对应用程序的影响。 ● 通常会使用一些技术来确保在标记和清除过程中,应用程序可以继续运行,如读屏障(Read Barrier)和写屏障(Write Barrier)等,
9.*redis当中常用的数据类型
String(字符串),
Hash(哈希),
List(列表),
Set(集合)、
Zset(有序集合)。
10.*redis的持久化策略
Redis持久化的意义:防止服务或系统宕机导致数据丢失。
Redis提供了两种持久化策略:RDB(Redis DataBase)、AOF(Append Only File)。
RDB:默认的持久化策略,将Redis存储的数据直接生成快照并进行持久化。 AOF:保存Redis执行过的指令记录,Redis重启时直接重新执行一遍指令即可恢复数据。
11.*redis当中的大key问题
Big Key就是某个key对应的value很大,占用的redis空间很大,本质上是大value问题。key往往是程序可以自行设置的,value往往不受程序控制,因此可能导致value很大。
redis中这些Big Key对应的value值很大,在序列化/反序列化过程中花费的时间很大,因此当我们操作Big Key时,通常比较耗时,这就可能导致redis发生阻塞,从而降低redis性能。
产生场景
1、redis数据结构使用不恰当 2、未及时清理垃圾数据 3、对业务预估不准确 4、明星、网红的粉丝列表、某条热点新闻的评论列表
Big Key的危害
1、阻塞请求 Big Key对应的value较大,我们对其进行读写的时候,需要耗费较长的时间,这样就可能阻塞后续的请求处理。Redis的核心线程是单线程,单线程中请求任务的处理是串行的,前面的任务完不成,后面的任务就处理不了。 2、内存增大 读取Big Key耗费的内存比正常Key会有所增大,如果不断变大,可能会引发OOM(内存溢出),或达到redis的最大内存maxmemory设置值引发写阻塞或重要Key被逐出。 3、阻塞网络 读取单value较大时会占用服务器网卡较多带宽,自身变慢的同时可能会影响该服务器上的其他Redis实例或者应用。 4、影响主从同步、主从切换 删除一个大Key造成主库较长时间的阻塞并引发同步中断或主从切换。
如何解决Big Key问题?
1、对大Key进行拆分 将一个Big Key拆分为多个key-value这样的小Key,并确保每个key的成员数量或者大小在合理范围内,然后再进行存储,通过get不同的key或者使用mget批量获取。 2、对大Key进行清理 对Redis中的大Key进行清理,从Redis中删除此类数据。Redis自4.0起提供了UNLINK命令,该命令能够以非阻塞的方式缓慢逐步的清理传入的Key,通过UNLINK,你可以安全的删除大Key甚至特大Key。 3、监控Redis的内存、网络带宽、超时等指标 通过监控系统并设置合理的Redis内存报警阈值来提醒我们此时可能有大Key正在产生,如:Redis内存使用率超过70%,Redis内存1小时内增长率超过20%等。 4、定期清理失效数据 如果某个Key有业务不断以增量方式写入大量的数据,并且忽略了其时效性,这样会导致大量的失效数据堆积。可以通过定时任务的方式,对失效数据进行清理。 5、压缩value 使用序列化、压缩算法将key的大小控制在合理范围内,但是需要注意序列化、反序列化都会带来一定的消耗。如果压缩后,value还是很大,那么可以进一步对key进行拆分。
12.***Mysql索引失效的场景
违反最左前缀法则 范围查询右边的列,不能使用索引 不能再索引的列上进行运算 字符串不做单引号,造成索引失效 模糊查询有可能导致索引失效,以%开头的模糊查询,索引失效
13.**sql语句的如何优化
尽量避免select *,改使用select 列名,避免返回多余的列。 sql避免造成索引失效的写法 尽量使用union all 代替union 避免在where子句中对字段进行表达式操作。 能用inner join就不要用left或rightjoin,如必须使用则要以小表驱动。
-
使用where条件语句限制要查询的数据,避免返回多余的行。
-
尽量避免select *,改使用select 列名,避免返回多余的列。
-
若插入数据过多,考虑批量插入。
-
尽量避免同时修改或删除过多数据。
-
尽量避免向客户端返回大数据量。
-
尽量避免使用子查询。
-
用IN来替换OR。
-
读取适当的记录LIMIT M,N,而不要读多余的记录。
14***Mysql数据库的优化
-
表的设计优化
-
设置合适的数值类型 设置合适的字符串类型
-
sql语句优化 select 后避免* sql避免造成索引失效的写法 尽量使用union all 代替union 避免在where子句中对字段进行表达式操作。 能用inner join就不要用left或rightjoin,如必须使用则要以小表驱动。
-
主从复制、读写分离
-
分库分表
-
选择最合适的字段属性,将表中字段的宽度舍得尽可能小。
-
尽量把字段设置为NOT NULL。
-
使用连接 (JOIN)来代替子查询 (Sub-Queries)。
-
使用联合 (UNION)来代替手动创建的临时表。
-
使用外键。
-
锁定表。
-
使用索引。
-
对查询进行优化,使用合适的索引,避免全表扫描。
15.*B+树索引与哈希索引的区别
1、如果是等值查询,那么hash索引有明显的优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个键值是唯一的,如果不唯一,则需要先找到下标位置再链式查找。 2、从示意图可以知道,hash索引无法支持范围查询,因为原先是有序的键值,但是经过hash算法后,有可能变成不连续的,就没有办法利用索引完成范围查询检索数据。 3、同样,hash索引也没办法利用索引完成排序,以及like xxx%
这样的模糊查询(范围查询)。 4、hash索引也不支持多列联合索引的最左前缀匹配规则。 5、B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键的情况下,hash索引的效率也是极低的,因为存在hash碰撞问题。
16.*列举一些Mysql当中的聚合函数
-
AVG() :只适用于数值类型的字段或变量。不包含NULL值
-
SUM() :只适用于数值类型的字段或变量。不包含NULL值
-
MAX() :适用于数值类型、字符串类型、日期时间类型的字段(或变量)不包含NULL值
-
MIN() :适用于数值类型、字符串类型、日期时间类型的字段(或变量)不包含NULL值
-
COUNT() :计算指定字段在查询结构中出现的个数(不包含NULL值)
17.*列举Mysql开窗函数
-
排名函数 ROW_NUMBER();
-
排名函数 RANK() 和 DENSE_RANK();
-
错行函数 lead()、lag();
-
取值函数 First_value()和last_value();
-
分箱函数 NTILE();
-
统计函数,也就是我们常用的聚合函数 MAX()、MIN()、AVG()、SUM()、COUNT()
18.Mysql事务的隔离级别
Read Uncommitted(读取未提交内容)
读未提交(read-uncommitted):能读到未提交的数据。会出现脏读、不可重复读、幻读。
Read Committed(读取提交内容)
读已提交(read-committed):读已提交的数据。会出现不可重复读和幻读 可以解决脏读问题。
Repeatable Read(可重复读)
可重复读(repeatable-read):mysql默认的事务隔离级别,查询的都是事务开始时的数据。只会出现幻读 可以解决脏读和不可重复读
Serializable(可串行化)
串行读(serializable):完全串行化读,每次都会锁表,读写互相阻塞。最高隔离级别,不会出现脏读,不可重复读,幻读。但会大大影响系统的性能,一般不用。
事务的定义: 一组操作,要么同时成功,要么同时失败,没有部分成功。 ACID(原子性,一致性,隔离性,持久性) redo: 持久性 undo: 原子和一致性
并发事务问题 脏读 A事务读到B事务没有提交的内容。 不可重复读 一个事务内读取两次,数据不一致。 幻读 查询时没有,但是插入时又发现有了。
19.*事务的四个特性
1、原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
2、一致性(Consistency) 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。 拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
3、隔离性(Isolation) 隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。 即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
4、持久性(Durability) 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。 例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交, 即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。