面试整理3

/*
 * 线程池的核心参数有哪些,执行流程是什么?、
 * corePoolSize 核心线程数
 * MaxPoolSize  最大线程数
 * threadFactory 线程工厂
 * KeepAliveTime 线程存活时间
 * workQueue 队列
 * policy 拒绝策略
 *
 * 当线程池接收到任务,会新建线程,知道当前线程数等于核心线程数,这时候,新来的任务都会放在队列中等待处理
 * 队列满了后,会新建线程直到当前线程数等于最大线程数,这时如果在来请求,就会执行拒绝策略
 * 如果线程空闲下来,并且队列中没有需要处理的任务,线程在存活时间等于keepaliveTeme的时候,救会被销毁
 * */

/*
 * HashMap的执行流程
 * 通过key的HashCode计算出元素的下标,判断他的存储位置,存储时,如果出现key不同的元素直接覆盖
 * 如果有key相同的元素,会放在链表后面,如果链表长度大于8,将会转成红黑树
 *
 * HashMap不是线程安全的,因为在put方法操作中, 没有被锁修饰,并且有个++count的操作
 *
 * HashMap扩容
 * 当map的中容量达到12,也就是16*0.75的时候,将会发生一次扩容、扩容为当选的两倍就是32
 *
 * 为什么负载因子是0.75
 * 如果负载因子过大,那么扩容的成本就提升了,空间利用率加大,并且发成冲突的概率也会提升,这时就需要更加复杂的数据结构来存储,查询时间下降浪费性能
 * 如果负载因子过小,库容成本降低,发生冲突的概率降低,但是空间利用率降低了,存储1M的数据却需要2M的空间
 * 并且map对容量有一个硬性的要求,容量必须是2的幂,而当负载因子是0.75的时候,容量正好是一个整数,综合,选取0.75
 *
 * HashMap允许key或者value为null,HashTable不允许,但是他是线程安全的,因为方法都被syn修饰了
 * 多线程情况下推荐使用concurrentHashMap,相比HashTable,它把Hash表分为i6个桶,每个桶都类似一个HashTabel
 * 并且相比HashTable,它的加锁方式更加精细,并发效果更好
 * */

/*
 * Spring的Ioc和Aop
 *
 * IOc 控制反转,就是说吧创建对象的权力交给了spring,,之前是用new创建对象,现在可以通过di注入,
 * 注入的方法有3种,注解注入,setter注入,构造方法注入
 *
 * AOP :面向切面编程
 * 底层是动态代理:就是在程序运行期间,在内存中生成一个aop对象,这个对象包含了目标类的全部方法,并且在特定的切点做的增强
 * Spring的AOP有两种 JDK 和CGLIB
 * JDK要求被代理的方法必须实现一个接口,核心方法是InvctionHanlder.proxy和invocake方法,当我们调用代理类对象的方法时候
 * 代理对象会作为invoke的参数proxy,method和arges传入
 * CGLIB:如果目标类没有实现接口,将会执行CGLIB动态代理,它其实就是一个类库,在运行时生成指定对象的一个子类,
 * 并且覆盖他特定的方法,覆盖方法时可以增强代码,从而实现AOP,CGLIB是通过继承来实现动态代理的,所以被代理的方法不能被final修饰
 * */

/*
 * SpringBean的生命周期
 * 1、实例一个对象,2、为对象甚至名称、factory等,3、在执行初始化之前,会调用BeanPostProcessorBeforeInit方法对Bean处理
 * 4、初始化Bean,5、初始化之后,会调用BeanPostProcessorAfter方法,6、当Bean不需要的时候,会对Bean进行销毁,调用destory-method
 * */

/*
 * BeanFactory和FactoryBean的区别
 * BeanFactory是一个工厂,用来管理所有的Bean,FactoryBean是一个Bean,需要经过前者的管理
 * */

/*
 * BeanFactory是最顶层的一个接口,提供了最简单的容器功能,负责读取、加载、实例维护bean
 * ApplicationContext是实现了BeanFactory的方法,包含的前者的所有功能吗,区别是BeanFactory每次只能加载一个Bean
 * 而后者可以在项目启动的时候,实例化全部的Bean
 * */

/*
 * Spring的作用域
 * 单例、多例、session、request
 * */

/*
 * 说一下Concurrent包下的类,
 * Runnable、Callable、timeUnit、ConcurrentHashMap、BlockQueue、ReentrantLock、ThreadFactory、Executor、future、lock
 * ReentWriteLock、ReentrantReadWriteLock
 * */

/*
 * 实现分布式锁的方法
 * 1、redis :jedis和redisson    jedis.set(key, UniqueId, "NX", "EX", seconds)
 * 2、数据库 :在数据库中加一个表,这个表包含几列:锁定的方法加索引、描述、保持数据的时间。释放锁直接删除数据
 * 3、Zookeeper :
 * */

/*
 * 线程的状态
 * new、runable、block、wait、计时等待、关闭
 * */

/*
 * dubbo的序列号方式
 * hession、java二进制、文本序列号、json
 * */

/*
 * 数据库的4大特性
 * 原子性:事务要么执行成功,要么失败,不会存在中间环节
 * 一致性:数据更改前和后,数据总体不发生改变
 * 隔离性:一个数据,同一时间只能有一个请求操作
 * 持久性:对数据的操作将永久保存在数据库中
 *
 * 数据库3范式
 * 1、一张表只描述一件事情 2、表中其他列都依赖其主键 3、从表的主键必须是主表的外键
 *
 * 数据库的隔离级别
 * 1、读未提交 2、读已提交 3、可持续读 4、串行化
 *
 * 事务的传播行为
 * */

/*
 * 锁
 * 公平锁、非公平锁 : 如果锁被其他线程获取,那么当前线程将会进入排队状态,等待线程释放锁。
 *                    如果当前线程在获取锁的时候,锁刚好释放,那么将会直接获取到锁,好处是可以尽快执行,因为唤醒下一个线程
 *                    可能需要一些时间,而在唤醒期间这个线程可能已经执行完了。坏处是可能导致后面线程一直没法得到锁,造成线程饥饿
 * 重入锁、不可重入锁 : 就是指当前线程在持有这把锁的情况下,可以在不释放锁的情况下,再次获取到这把锁
 * 悲观锁、乐观锁 :悲观锁就是指,认为默认认为会有其他线程在我操作的时候修改数据,所有要操作,必须先获取到这把锁
 *                 乐观锁就是默认不会有其他线程修改数据,但是自己在操作前会判断数据有没有被其他线程修改过,使用的cas思想
 * 共享锁、独占锁 : 共享锁就是指一把锁可以同时被多个线程获取到 读锁就是共享锁,写锁就是独占锁
 * */

/*
 * redis
 * 数据结构:string、list、set、zset、hash
 * 持久化方式:RDB、AOF 快照:把当前数据当作快照存储下来,把当前所有操作指令记录下来。丢失数据、占用硬盘空间
 * 雪崩:指同一时间大面积的key失效,导致数据库链接异常 :给key设置一个随机的失效时间
 * 穿透:就是指用户不断发起请求的数据,在缓存和DB中都没有
 *       方法二:在缓存查不到,DB中也没有的情况,可以将对应的key的value写为null,或者其他特殊值写入缓存,
 *               同时将过期失效时间设置短一点,以免影响正常情况。这样是可以防止反复用同一个ID来暴力攻击。
 *       方法三:正常用户是不会这样暴力功击,只有是恶意者才会这样做,可以在网关NG作一个配置项,为每一个IP设置访问阀值。
 * 击穿:缓存击穿是指一个key是热点,不停地扛住大并发请求,全都集中访问此key,而当此key过期瞬间,持续的大并发就击穿缓存,全都打在DB上。就又引发雪崩的问题。
 *       解决方案:设置热点key不过期。或者加上互斥锁。
 *
 * redis中如何做到数据同步
 * 1、使用定时任务,定时同步数据到redis
 * 2、如果数据库执行增删改的操作,就清除reids,下次执行查询的时候查redis没有数据,就会更新到redis最新的
 * */

/*
 * 消息队列
 * 如何保证消息的有序性:可以给消息设置一个全局唯一的递增序列号,通过比较序列号来确定先后顺序
 * 如何保证消息不被重复消费:创建一张表用来存储消息的id,已经被消费过的id会放在表里,存在表中的id不会二次被消费
 * mq积压了几百万条数据怎么办:
 *   1、先修复consumer的问题,确保其恢复消费速度,然后将现有cnosumer都停掉
 *   2、新建一个topic,partition是原来的10倍,临时建立好原先10倍或者20倍的queue数量
 *   3、然后写一个临时的分发数据的consumer程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的10倍数量的queue
 *   4、接着临时征用10倍的机器来部署consumer,每一批consumer消费一个临时queue的数据
 *   5、这种做法相当于是临时将queue资源和consumer资源扩大10倍,以正常的10倍速度来消费数据
 *   6、等快速消费完积压数据之后,得恢复原先部署架构,重新用原先的consumer机器来消费消息
 *
 * 秒杀环境如何保证数据不超卖/就剩下一个商品,两个人同时下单,如何解决:使用mq
 * */

/*
 * 项目是如何解决并发问题的
 * 1、数据层
 *   集群、分库分表、开启索引、优化sql、搭建缓存服务器、搭建搜索服务器
 * 2、项目层
 *   采用分布式架构、使用静态页面、使用mq解耦、使用分布式文件存储系统
 * 3、应用层
 *   使用nginx负载均衡、LVS做二层负载
 * */

/*
 * mysql优化
 * sql优化
 *       1、SELECT语句务必指明字段名称
 *       2、当只需要一条数据的时候,使用limit 1
 *       3、如果排序字段没有用到索引,就尽量少排序
 *       4、如果限制条件中其他字段没有索引,尽量少用or、
 *       5、尽量用union all代替union
 *       6、不使用ORDER BY RAND()
 *       7、关于not in和not exists,推荐使用not exists
 *       8、避免在 where 子句中对字段进行 null 值判断
 *       9、不建议使用%前缀模糊查询
 *       10、避免在where子句中对字段进行表达式操作
 *       11、SQL语句中IN包含的值不应过多
 * 硬件优化
 *      1、分库分表
 *      2、使用缓存
 *      3、使用读写能力高的磁盘
 *
 *
 * 索引分类
 *      1、普通索引 2、唯一索引 3、主键索引 4、复合索引 5、全文索引
*		数据库存储引起MyLsam和Innodb的区别
*		 1、Innodb支持事务,MyLsam不支持事务
*		 2、Innodb支持行锁,MyLsam不支持
*		 3、Innodb支持外键,MyLsam不支持
*		 4、Innodb是索引表,MyLsam是堆表
*		 5、Innodb支持全文索引,MyLsam不支持
 * */

/*
 * 单例模式
 * 单例模式是指在内存中只会创建且仅创建一次对象的设计模式
 *  public class Singlton {
 *      private static Singlton singlton;
 *      private Singlton(){};
 *      public static Singlton getSinglton(){
 *           Singlton singlton = new Singlton();
 *           return singlton;
 *      }
 *  }
 * */

/*
* java内存模型约定了所有变量都必须存储在主内存中,每个线程拥有自己的工作内存,保存主内存的变量副本,线程之间的变量修改不可见
* 指令重排序是指:JVM 在保证最终结果正确的情况下,可以不按照程序编码的顺序执行语句,尽可能提高程序的性能
* 使用 volatile 关键字修饰的变量,可以保证其指令执行的顺序与程序指明的顺序一致,不会发生顺序变换
* 使用 volatile 关键字修饰的变量,可以保证其内存可见性,即每一时刻线程读取到该变量的值都是内存中最新的那个值,线程每次操作该变量都需要先读取该变量。
* */

/*

  • 脏读 :操作A更新了一条时间,操作B读取了更新的数据,但是A操作回滚了,则B操作读取的数据就不对了
    幻读 :两次查询数据不一致
    不可重复读 :一个事务读取同一条记录2次,得到的结果不一致:

SQL优化
主要是为了避免索引失效
比如:1、不对where子句中进行null判断
2、或者不适用!= 、< >操作符
3、使用exit 代替not in
4、不在where子句中进行函数操作
**/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值