面试系列-淘天提前批面试

时间:2024-10-07 17:49:04

00-淘天提前批面试

在牛客上看到了淘天提前批的面试题目,这里分析一下淘天面试的问了有哪些内容,面试的重点 是偏向哪些方面

项目相关

1、秒杀架构如何设计?

问了秒杀的架构如何设计,对于秒杀的设计,秒杀符合 写多读少 的场景,那么针对 写比较多 的场景,可以将 Redis 作为 主存储 来操作,这样并发度比较高,Redis 扣减成功之后,再通过 异步 去 DB 中扣减库存,将耗时操作从主干流程中剥离出去,提升主干流程的响应速度,这是从性能的方面进行设计

不过基于 Redis 进行操作的话,Redis 集群部署时,在极端情况下,如果 Redis Master 上扣减库存之后,宕机,此时数据还没来得及同步到 Slave 节点,此时就会出现 库存超卖 的情况,不过这种情况概率很低,并且如果库存超卖的话,只要在订单系统中有防超卖机制即可

2、项目的 QPS 是多少?

这个问的是有没有对项目接口进行压测,一般部署 Prometheus、Grafana 对机器、应用进行监控,再通过 JMeter 进行压测即可,不过说 QPS 时,要先说明机器使用的配置,一般我们学生在学习时,使用 2C4G 服务器进行压测居多(比较便宜)

3、TPS 和 QPS 的区别是什么?

这个就是应用的 性能指标 ,TPS 是指应用每秒处理的事务数量,QPS 是指应用每秒处理的请求数量,一般情况下 QPS 是要多于 TPS 的,因为一个事务中可能包含多个增删改查

基础能力

try catch

问题 :在 try catch finally 中,如果在 try 中 return 了,还会执行 finally 吗?

会执行的,这里应该问的就是 try catch finally 的 return 执行顺序,如下:

1、try、catch 中没有 return 语句

当try和catch中都没有return语句时, 执行顺序依次为:

try --> 执行发生异常 --> catch --> finally

2、try、catch 中有 return 语句,finally 中没有 return。

先把 try 或 catch 中的 return 值保存在局部变量中,再去执行 finally 中的语句,最后 return 返回

3、try、catch 中有 return 语句,且 finally 中也有 return finally 中的 return 最后会覆盖 try、catch 中的 return 数据

问题2 :在 finally 中一般关闭资源,如果出现异常怎么处理?

打印日志进行记录就好了

如果在 finally 中关闭资源要再 try catch 的话,那代码也太臃肿了,我看了 RocketMQ 相关的源码,在 finally 中没有在 finally 中再进行其他的一些重试操作(如果不对,请指正)

final

问题1 : final 放在类上有什么用?

final 放在类上表明该类 不可以被继承 ,主要是为了保证 类的安全性

如果 final 修饰方法,则该方法也不可以被 重写

扩展

  • private 方法会被隐式指定为 final 方法
  • final 修饰的成员变量使用前要初始化

问题2 :final 修饰 HashMap,可以向这个 Map 中添加元素吗?

可以的

final 修饰变量的话,有两种情况:

  • final 修饰基础类型变量 :则数值在初始化之后,就无法更改
  • final 修饰引用类型变量 :则初始化之后,不可以再指向其他对象,但是可以修改该引用类型变量内部的值

多线程

问题1 :五个线程 abcde 如果想先执行 a,再执行 bcd,bcd 执行完后执行 e 如何做?

可以使用 CompletableFuture 来 做多个任务的编排 ,如下:

public class Main {
    public static void main(String[] args) {
        CompletableFuture<Void> taskA = CompletableFuture.runAsync(() -> {
            System.out.println("Thread a is running.");
        });

        CompletableFuture<Void> taskB = taskA.thenRun(() -> {
            System.out.println("Thread b is running.");
        });

        CompletableFuture<Void> taskC = taskA.thenRun(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("Thread c is running.");
        });

        CompletableFuture<Void> taskD = taskA.thenRun(() -> {
            System.out.println("Thread d is running.");
        });

        CompletableFuture<Void> taskE = CompletableFuture.allOf(taskB, taskC, taskD).thenRun(() -> {
            System.out.println("Thread e is running.");
        });

        taskE.join(); // 等待所有任务执行完成
    }
}

问题2 :用过 CountDownLatch 吗?

CountDownLatch 是 JUC 包下边的工具类,使用场景 为:有多个子任务,此时需要这么多的子任务都执行完毕之后,再去执行主干流程,如果有任何一个任务没有执行完毕都会阻塞等待

如下:

public class Main {
   public static void main(String[] args) throws InterruptedException {

      CountDownLatch countDownLatch = new CountDownLatch(6);

      for (int i = 1; i <= 6; i ++) {
         new Thread(()->{
            System.out.println(Thread.currentThread().getName() + "执行任务");
            countDownLatch.countDown();
         }, String.valueOf(i)).start();
      }

      // 等待子线程执行任务
      countDownLatch.await();

      // 主线程继续向下执行...
   }
}

问题3: Thread.sleep() 有用过吗?会放弃 CPU 锁吗?如果需要让出时间片,该通过什么方式让出?

Thread.sleep() 方法不会让线程放弃 CPU 锁的占用,但是会释放 CPU 时间片

线程还可以通过 Thread.yield() 方法来让出 CPU 时间片,但是可能线程刚刚让出 CPU 时间片,又会重新获取 CPU 时间片继续执行

synchronized

问题1: 你一般会使用 synchronized 锁在方法上吗?如果是锁对象,这个对象如何确定下来呢?

如果是整个方法需要同步的话,那么就可以将 synchronized 放在方法上,synchronized 锁在方法上和锁在对象上的区别就是: 锁的粒度不同

synchronized 锁在对象上,可以让锁的粒度更小,并发度更高

synchronized 锁对象的话,只要保证多个线程去执行 synchronized 并发代码块的时候,可以取到同一个对象即可,也就是保证这个对象是单例的

问题2: synchronized 锁在 this 上可以吗?

可以的,锁定 this 对象就是锁定当前这个实例对象,我们的工程一般都是基于 Spring 的,Spring 中的 Bean 都是单例的,因此通过 synchronized 可以达到同步的效果

HashMap

问题1: HashMap 扩容和树化说一下

HashMap 的 扩容 条件:当 HashMap 中数组的元素个数超过了 当前容量 * 负载因子(默认0.75) 就会触发扩容,会将数组长度扩容为原来的 2 倍

HashMap 的 树化 条件:当数组长度达到 64 并且链表长度超过 8 就会进行树化(如果链表长度超过 8,但是数组长度不到 64,就会对数组扩容 1 次,而不会执行树化)

问题2: 你知道红黑树每次翻转高度差的变化么?

每次翻转之后,要么是左旋要么是右旋,每次旋转之后高度会减 1,来保证稳定

可以在这个网站中自己插入节点看一下红黑树的旋转情况比较直观:cs.usfca.edu