Java基础篇:
- List接口下有哪些类?它们的区别?
1.ArrayList:底层是动态数组;查询快,插入和删除慢;线程不安全的。
2.LinkedList:底层是双向链表;插入和删除快,查询慢;线程不安全的。
3.Vector:底层和ArrayList一样;查询快,插入和删除慢;线程安全的。
拓展:为什么Vector是线程安全的,因为它的方法都加了synchronized关键字修饰。
- 线程的创建方式?
Thread
Runable
Callable
线程池
- 阻塞队列是什么意思?
阻塞队列(BlockingQueue) 是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。
- jdk1.7中有哪些阻塞队列?
ArrayBlockingQueue : 一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue : 一个由链表结构组成的有界阻塞队列。
PriorityBlockingQueue : 一个支持优先级排序的无界阻塞队列。
DelayQueue: 一个使用优先级队列实现的无界阻塞队列。
SynchronousQueue: 一个不存储元素的阻塞队列。
LinkedTransferQueue: 一个由链表结构组成的无界阻塞队列。
LinkedBlockingDeque: 一个由链表结构组成的双向阻塞队列。
- 启动线程为什么要先Start(),在Run()?
1.start()方法来启动线程,真正实现了多线程运行。这时无需等待run方法体代码执行完毕,可以直接继续执行下面的代码;通过调用Thread类的start()方法来启动一个线程, 这时此线程是处于就绪状态, 并没有运行。 然后通过此Thread类调用方法run()来完成其运行操作的, 这里方法run()称为线程体,它包含了要执行的这个线程的内容, Run方法运行结束, 此线程终止。然后CPU再调度其它线程。
2.run()方法当作普通方法的方式调用。程序还是要顺序执行,要等待run方法体执行完毕后,才可继续执行下面的代码; 程序中只有主线程——这一个线程, 其程序执行路径还是只有一条, 这样就没有达到写线程的目的。
框架篇:
- mybatis中dao(Mapper)接口的原理?
Dao接口的工作原理是JDK动态代理,MyBatis运行时会使用JDK动态代理,为Dao接口生成代理proxy对象,代理proxy对象会拦截接口方法,转而执行MappedStatement所代表的sql,然就将执行结果返回。
Mapper 接口开发需要遵循以下规范:
- Mapper.xml文件中的namespace与mapper接口的全限定名相同
- Mapper接口方法名和Mapper.xml中定义的每个statement的id相同
- Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同
- Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
- Spring中依赖注入(DI)和控制反转(IoC)?
IoC和DI其实是同一概念的不同角度描述。IoC强调的是将对象实例的创建控制权由spring容器来统一管理,需要的时候从容器中取出,而不是由调用者自身去创建,从而达到降低代码耦合性与硬代码的目的。依赖注入强调的是当调用者需要使用对象实例时,spring容器为调用者提供对象实例这个过程。本质上应该是属于同一技术实现方式,但是在不同的情况,叫法不同。就好比张三在村里住的时候,邻居叫他狗蛋,但是出到外面打工,别人叫他张三一样。
- Spring中如何解决循环依赖?
有A,B两个类,A类中有B类属性,B类中有A类属性。加载过程,首先创建A类,先从ApplicationContext.getBean()获取A类,这时A类不存在,所以创建一个A类,接下来就是创建A中B类的属性,同样是使用ApplicationContext.getBean()来获取B类,这时B类也不存在,所以要创建一个B类,接下来就是创建B类中A类的属性了,还是调用ApplicationContext.getBean()方法,不过这次会从缓存中得到一个A类的半成品,给A属性,创建好了之后,B类也创建好了,给B属性,这时A类也创建完成。其中B类得到的A类的半成品,和A类是同一个引用地址。所以是一个对象。(ApplicationContext.getBean()方法是通过doGetBean来获取对象,而doGetBean是通过GetSingleton来获取对象)
- 用过哪些mybatis的插件?有没有写过?
mybatis-generator:根据数据库自动生成pojo、dao和xml文件。
mybatis-plugin:这是一个能够追踪dao 接口和mapper文件里xml的一个插件
mybatis-pagehelper:它是一个开源的分页插件点击打开链接,它的原理,是通过spring的AOP来实现的,这个插件能在执行sql的时候,把相关的数据再执行一次。
中间件篇:
- redis主从复制的应用
读写分离:主从复制可以用来支持读写分离
数据安全:slave 服务器设定为只读
避免 master 持久化造成的开销
- redis的缓存穿透和雪崩原理?
缓存雪崩:指在我们设置缓存时,key采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩
解决方案:
1.使用 Redis 高可用架构:使用 Redis 集群来保证 Redis 服务不会挂掉
2. 缓存时间不一致,给缓存的失效时间,加上一个随机值,避免集体失效
3. 限流降级策略:有一定的备案,比如个性推荐服务不可用了,换成热点数据推荐服务
缓存穿透:指查询大量为null的数据,导致数据库压力增大
解决方案:
1.在接口做校验
2.存null值(缓存击穿加锁)
3.布隆过滤器拦截: 将所有可能的查询key 先映射到布隆过滤器中,查
时先判断key是否存在布隆过滤器中,存在才继续向下执行,如果不存在,则直接返回。布隆过滤器将值进行多次哈希bit存储,布隆过滤器说某个元素在,可能会被误判。布隆过滤器说某个元素不在,那么一定不在。
- zookeeper的选举机制?
目前有5台服务器,每台服务器均没有数据,它们的编号分别是1,2,3,4,5,按编号依次启动,它们的选择举过程如下:
- 服务器1启动,给自己投票,然后发投票信息,由于其它机器还没有启动所以它收不到反馈信息,服务器1的状态一直属于Looking。
- 服务器2启动,给自己投票,同时与之前启动的服务器1交换结果,由于服务器2的编号大所以服务器2胜出,但此时投票数没有大于半数,所以两个服务器的状态依然是LOOKING。
- 服务器3启动,给自己投票,同时与之前启动的服务器1,2交换信息,由于服务器3的编号最大所以服务器3胜出,此时投票数正好大于半数,所以服务器3成为leader,服务器1,2成为follower。
- 服务器4启动,给自己投票,同时与之前启动的服务器1,2,3交换信息,尽管服务器4的编号大,但之前服务器3已经胜出,所以服务器4只能成为follower。
- 服务器5启动,后面的逻辑同服务器4成为follower。