面试题笔记

一、Java面试-创建对象,你有几种方法?

二、MySQL数据库为什么要用innodb

1、支持事务;2、实现了MySQL的mvcc;3、支持行级锁;
View Code

三、Spring各个注解:Xmind:SpringCloud -> 注解

四、redis的优缺点,以及应该注意什么:

优点:
1)基于内存,操作速度快;
2)丰富的数据类型,有STRING,LIST,HASH,SET,SORTEDSET,二那个什么mach的什么什么只支持单一的数据类型STRING;
3)支持事务;
4)原子性操作;
5)支持持久化策略:AOF和RDB

缺点:
数据不一致;代码维护成本

应该注意什么:
其实就是问  缓存穿透、缓存雪崩、缓存击穿;Xmind:redis -> 使用redis应注意什么
View Code

七、如果给7亿数据你,你怎么处理这些数据;我回答了集群,多主多从,一主对多从,读写分离的架构模式;然后对方问在多主的情况下,这7亿数据,你应该怎么分配到这若干台主机上面,如果业务突然要求要额外导3亿数据进来,允许你增加机器,比如说增加了3台,你怎么很好地结合本来的七亿数据????一定要记住这个哦

主要是从一致性hash的hash环原理来改进
View Code

九、什么时候用到多线程;谈谈你对锁的理解

十、wait状态和runnable状态之间是什么?(难道是wait方法的调用???)

十一、请设计一下电商秒杀系统的实现方式?SETNX;悲观锁思路, FIFO思路,乐观锁思路;(业务分离、限流、降级、熔断、redis集群、消息队列)

    private boolean checkSoldCountByRedisDate(String key, int limitCount, int buyCount, Date endDate, String lock, int expire) {
        boolean check = false;
        if (this.lock(lock, expire)) {
            Integer soldCount = (Integer) redisUtil.get(key);
            Integer totalSoldCount = (soldCount == null ? 0 : soldCount) + buyCount;
            if (totalSoldCount <= limitCount) {
                redisUtil.set(key, totalSoldCount, DateUtil.diffDateTime(endDate, new Date()));
                check = true;
            }
            redisUtil.remove(lock);
        } else {
            if (this.unDieLock(lock)) {
                logger.info("解决了出现的死锁");
            } else {
                throw new ServiceException("活动太火爆啦,请稍后重试");
            }
        }
        return check;
    }
View Code

十二、springmvc如何实现异步响应?

十三、MySQL根据一组id查结果如何保证顺序?redis如何批量查询多个key?

十四、什么是分布式锁?· 如何实现分布式锁?· 单机锁有哪些?它为什么不能在分布式环境下使用?· Redis 是如何实现分布式锁?可能会遇到什么问题?· 分布式锁使用超时的话会有什么问题?如何解决?

  提示:redis官网 -》文档 -》分布式锁

十五、redis 字符串数据结构内部实现

简单动态字符串
好像不止
View Code

十七、乐观锁的实现方式(版本号,cas,自旋,ABA问题)

十八、try代码块中有return,又有finally代码块:先执行finally代码块里面的,再执行try代码块里面的return语句

十九、关于JAVA中String类以形参传递到函数里面,修改后外面引用不能获取到更改后的值

二十、string是线性安全的吗?

首先得明白为什么会有线程安全这个问题,之所以要考虑线程安全,是因为变量是可变的,可以被其他线程修改。如果这种情况发生了,就是线程不安全了。

如果这个变量本身都不可以变了,也就谈不上那个什么线程安全不安全了,或者说肯定是线程安全的。比如String,因为根本改不了啊。
View Code

二十一、AOP的原理:草,代理模式的jdk动态代理我都忘记了,草,innovationHander;或者cglib字节码增强方式

二十二、mybatis怎么引入另外一个xml文件里面的内容:叼,多增加一个namespace的内容就可以了,为什么当时做社保的时候我不去查一下,叼;

二十三、AOP的应用场景:日志埋点(这个自己做过)、用户登录(好像有印象这个有)、权限(当时听讲课的时候听过)、事务(懵逼)

二十四、依赖注入的方式有几种(这个问题我不懂)

二十五、spring的优点

二十六、聊一下jvm内存(我从新生代老年代这个角度回答)

二十七、你在项目中哪里用到了redis,聊一下redis,你的redis内存是多大,过期时间是的多少

二十八、hashmap  你对他的了解? (结构)jdk1.7 :数组+链表   jdk1.8:数组+链表+红黑树     ;   hahsmap是怎么初始化的:jdk1.7(new的时候已经分配空间) 1.8(new的时候还没有分配空间,put的时候才分配空间),空间是16,负载因子是0.8; hashmap是怎么找key的;

二十九、arraylist 线程安全的是不是?不是。怎么使她线程安全?vector(过期),DD ARR = sync.xxx(arraylist)  (颗粒度很大)?并发容器:copyrigtharrlylist(颗粒度小):数据结构?副本??concurrenthashmap

 三十、依赖注入注入的方式

三十一、syncroneze和lock的区别

一、java面试之clone()

二、redis为什么这么快:

    1)完全基于内存操作;

     2)数据结构数据操作简单,也对数据结构进行了专门的优化;

     3)采用单线程,避免了不必要的上下文切换以及竞争条件(采用单线程操作就已经很快了,所以就不必要采用多线程了);

     4)采用了多路复用IO
View Code

三、Redis过期策略

四、Redis 内存淘汰机制:在redis.conf里面配:maxmemory <bytes>;

      默认:当内存使用达到阈值的时候,所有引起申请内存的命令会报错

      在带有过期时间的键中选择最近最少使用的。(推荐)

      在所有的键中选择最近最少使用的。(不区分是否携带过期时间)(一般推荐)

五、同步容器、并发容器

六、乐观锁、悲观锁:我们平时看到的:synchronized 以及ReentrantLock 就是悲观锁

       乐观锁的版本号方法:当我们要从数据库中读取数据的时候,同时把这个version字段也读出来,如果要对读出来的数据进行更新后写回数据库,则需要将version加1,同时将新的数据与新的version更新到数据表中,且必须在更新的时候同时检查目前数据库里version值 是不是之前的那个version,如果是,则正常更新。如果不是,则更新失败,说明在这个过程中有其它的进程去更新过数据了。

七、分布式锁过程当中,怎么解决setnx,setex的问题:1)用lua脚本,里面就是原子性了;2)后来的新本来setnx,setex可以用一条命令来替代了;

八、你知道Redis读写分离是怎么做数据同步的吗:数据的一致性

九、分布式高可用经典架构环节分析

【客户端层】到【反向代理层】的高可用,是通过反向代理层的冗余来实现的。以nginx为例:有两台
nginx,一台对线上提供服务,另一台冗余以保证高可用, 常见的实践是keepalived存活探测
【反向代理层】到【web应用】的高可用,是通过站点层的冗余来实现的。假设反向代理层是nginx,
nginx.conf里能够配置多个web后端,并且nginx能够探测到多个后端的存活性。
自动故障转移:当web-server挂了的时候,nginx能够探测到,会自动的进行故障转移,将流量
自动迁移到其他的web-server,整个过程由nginx自动完成,对调用方是透明的。
【服务层】到【缓存层】的高可用,是通过缓存数据的冗余来实现的。 redis天然支持主从同步,redis
官方也有sentinel哨兵机制,来做redis的存活性检测。
【服务层】到【数据库层】的高可用,数据库层用“主从同步,读写分离”架构,所以数据库层的高可
用,又分为“读库高可用”与“写库高可用”两类。
读库采用冗余的方式实现高可用,写库采用keepalived存活探测 binlog进行同步
View Code

十、微服务高并发如何处理:ribbon 负载均衡、redis集群(三主三从、读写分离)

首先业务分离(就是把秒杀服务器与网站其他服务器完全隔离,以防流量过大带着其他服务一起死,要死你就死吧,把配置高的服务器都用来秒杀),最前端的页面要被CDN或反向代理是肯定的,之后限流(比如服务器只能承受10W流量,高于10W的请求直接返回失败),降级(秒杀页面并发高到一定程度时可以断开某些接口查询,如推荐,相似物品,历史价格等等,减少服务器返回时间),熔断(某些接口大于某个流量活并发峰值直接返回失败,或者返回默认数据如:某些产品一直有货 ),然后进入到负载均衡器中,负载均衡器分配到web服务器中,web服务器在进入队列,之后进入一个统一的缓存计数器中,秒杀结束后,通过秒杀日志,worker计算剩余库存(此处为异步处理),并且使用MQ推送下单信息至各个系统(订单,库存,发货,子业务域。。。等等系统),各个系统处理后写入数据库。这么大流量的系统想要保证数据库中与前台库存与缓存的一致性几乎不可能,但是我们只要保证最终落表的数据是正确的就行,如同上文中使用worker读取日志采用异步的方式进行数据落表处理(当然方法还有很多,这里只介绍一个典型方案),这就是传说中的弱一致性保持,分布式系统CAP中通常都会牺牲掉C推荐 @李智慧 的图书《大型网站技术架构》反复阅读后每次都有新的感悟
View Code

十一、concurrentHashMap 如何实现线程安全  注意jdk1.7和jdk1.8的区别

十二、多线程-CAS原理

十三、关于Integer和int的比较

    public static void main(String[] args) {
        Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
        System. out.println( f1 == f2);
        System. out.println( f3 == f4);

        Integer a = new Integer(3);
        Integer b = 3;
        int c = 3;
        System.out.println(a == b);
        System.out.println(a == c);
    }
View Code

 十四、threadlocal 源码中是用map来实现的,其中key值是什么

*** 线程池中的参数你了解多少

***  AKF 拆分原则

*** 为什么buffer IO b比 一般的 IO 快:

  因为buffefr IO 是到了 8K 才调内核态往磁盘里面写数据,但是一般的IO,它是每写一次就调一次内核态,用户态与内核态之间切换是需要性能的。

 十五、设计模式

鸭子策略模式
流用的是包装模式
NETTY用的是反应器模式
顺丰那里用的是一个密码对象,加密解密用一个对象就可以了
代码模式,AOP就是用JDK动态代理来的
View Code

十六、springcloud的各个组件,你了解多少

服务治理与发现:要说出3个
服务之间调用:也要说出三个,ribbon的负载均衡,不过现在一般都是NG做负载均衡的啦
断路器:要说出一个,说白了就是服务之间调用,多久没有相应,就要进行另外一个操作(熔断);
        一个服务挂了,没有这个服务,还是可以继续工作的(降级)。服务分发,路由
服务网关:zuul,域名映射,那些路径请求可以进,哪些不可以进
分布式配置:config组件,记得自己项目用的是applo哦
View Code

十七、类的初始化

/**
 * 加载这个类的时候,必须加载其静态代码块
 *
 * LazyLoading 五种情况
 *
 * 1)–new getstatic putstatic invokestatic指令,访问final变量除外
 *
 * 2)–java.lang.reflect对类进行反射调用时
 *
 * 3)–初始化子类的时候,父类首先初始化
 *
 * 4)–虚拟机启动时,被执行的主类必须初始化:所以一定会打印 T008_LazyLoading
 *
 * 5)–动态语言支持java.lang.invoke.MethodHandle解析的结果为REF_getstatic REF_putstatic REF_invokestatic的方法句柄时,该类必须初始化
 */
public class T008_LazyLoading { //严格讲应该叫lazy initialzing,因为java虚拟机规范并没有严格规定什么时候必须loading,但严格规定了什么时候initialzing
    static {
        System.out.println("T008_LazyLoading");
    }
    public static void main(String[] args) throws Exception {
        // 没有new,没有访问不会被加载:只打印 T008_LazyLoading
//        P p;
        // 符合第三条嘛:打印 T008_LazyLoading P X
//        X x = new X();
        // 父类的加载,跟子类一毛钱关系都没有:打印 T008_LazyLoading P
//        P p = new P();
        // final值不需要初始化这个类:个人理解是因为 final值在一开始的时候就已经放进方法区的常量池里面了,跟类的初始化没有关系
//        System.out.println(P.i);
        // 打印 T008_LazyLoading  P   9:尼玛,静态成员变量是跟随着类的初始化的
//        System.out.println(P.j);
        // 打印 T008_LazyLoading P : 符合第二点
        Class.forName("com.mashibing.jvm.c2_classloader.T008_LazyLoading$P");

    }

    public static class P {
        final static int i = 8;
        static int j = 9;
        static {
            System.out.println("P");
        }
    }

    public static class X extends P {
        static {
            System.out.println("X");
        }
    }
}
View Code

 20200731 平安普惠外包

一、ConcurrentHashMap 的数据结构

二、线程池设定的那个时间是多少?然后我说不知道,那边就抛出一个,这个东东不是你配的吗

三、MQ我的痛

end!

原文地址:https://www.cnblogs.com/ericguoxiaofeng/p/10672109.html