传音控股Java 一面+二面

传音控股Java 一面+二面
最新回答
涟漪幽香

2024-04-12 17:19:20

一面问题解答
  1. 后端开发女生少,你觉得比男的有什么优势

    沟通协作优势:女生通常在沟通方面更具细腻和耐心,在团队协作中能更有效地倾听他人意见,促进团队成员间的信息交流,减少误解,提高协作效率。例如在需求讨论阶段,可以更全面地理解各方需求,准确传达开发相关问题。

    细节把控优势:在开发过程中,对代码的细节处理更为严谨,能够减少因粗心导致的错误。比如在编写复杂业务逻辑代码时,对变量命名、代码注释等细节会更注重,提高代码的可读性和可维护性。

    多任务处理优势:面对多个任务并行时,女生往往能更好地平衡和安排任务优先级,有条不紊地推进工作。例如同时处理多个接口开发和 bug 修复任务时,能合理分配时间和精力。

  2. 职业规划,有没有考虑单纯开发和团队管理之间的区别,如果你带团队应该怎么做

    区别

    单纯开发:主要聚焦于技术实现,深入钻研代码编写、算法设计、性能优化等技术细节,通过不断提升个人技术能力完成项目中的开发任务。

    团队管理:除了具备一定的技术能力外,还需关注团队成员的成长和发展、项目进度把控、资源协调等方面。要制定合理的项目计划,激励团队成员,解决团队内部矛盾,确保项目顺利推进。

    带团队做法

    明确目标:为团队设定清晰、可衡量的目标,让每个成员都清楚了解工作方向和重点。

    合理分工:根据成员的技术特长和优势分配任务,充分发挥每个人的潜力,提高工作效率。

    沟通协作:建立有效的沟通机制,定期组织团队会议,及时解决成员遇到的问题,促进成员之间的信息共享和协作。

    激励成长:关注成员的职业发展,提供培训和学习机会,鼓励成员不断学习和进步,对表现优秀的成员给予适当奖励。

  3. hashmap的扩容

    触发条件:当 HashMap 中的元素数量超过负载因子(默认 0.75)乘以初始容量时,就会触发扩容。例如初始容量为 16,当元素数量达到 16 * 0.75 = 12 时,就可能触发扩容。

    扩容过程:创建一个新的数组,其容量是原数组容量的 2 倍。然后遍历原数组中的每个元素,重新计算其在新数组中的位置(通过哈希函数和新的数组长度),并将元素移动到新数组中。

  4. 线程池的参数,如果 8 核,核心线程怎么设置

    线程池参数:包括核心线程数、最大线程数、空闲线程存活时间、工作队列等。

    8 核核心线程设置:一般可以将核心线程数设置为 CPU 核心数或略大于 CPU 核心数,对于 8 核 CPU,可以将核心线程数设置为 8 或 10 左右,这样可以充分利用 CPU 资源,提高并发处理能力。

  5. 锁的升级过程

    无锁状态:对象刚创建时处于无锁状态,任何线程都可以访问。

    偏向锁:当第一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程 ID,后续该线程进入同步块时无需进行任何同步操作,提高性能。

    轻量级锁:当有第二个线程竞争偏向锁时,偏向锁会升级为轻量级锁。线程通过自旋的方式尝试获取锁,不会阻塞线程,减少上下文切换开销。

    重量级锁:如果自旋次数过多或竞争激烈,轻量级锁会升级为重量级锁。此时线程会阻塞,进入等待队列,直到获取到锁。

  6. 索引分类,聚簇索引和非聚簇索引

    聚簇索引:索引的叶子节点存储了完整的数据记录,数据按照聚簇索引的顺序物理存储。一个表只能有一个聚簇索引,通常主键就是聚簇索引,它可以提高按主键查询的速度。

    非聚簇索引:索引的叶子节点存储的是主键值,而不是完整的数据记录。通过非聚簇索引查询数据时,需要先根据索引找到主键值,再通过主键值去聚簇索引中查找完整的数据,一个表可以有多个非聚簇索引。

  7. MySQL 的两种引擎,哪个支持事务

    InnoDB 引擎:支持事务,具有事务的 ACID 特性(原子性、一致性、隔离性、持久性),能够保证数据的完整性和一致性,适合对数据安全性要求较高的应用。

    MyISAM 引擎:不支持事务,它只支持表级锁,查询速度较快,但在并发写入时性能较差,适用于读多写少的场景。

  8. 索引的创建规则

    选择合适的列:选择经常用于查询条件、排序和分组的列创建索引,如 WHERE 子句中的列、ORDER BY 子句中的列等。

    避免过多索引:索引会占用额外的存储空间,并且在插入、更新和删除数据时会维护索引,影响性能。因此不要创建过多不必要的索引。

    考虑索引的选择性:选择性高的列(即列中不同值的数量较多)更适合创建索引,这样可以更有效地缩小查询范围。

    复合索引的顺序:对于复合索引,将选择性高的列放在前面,遵循最左前缀原则,即查询条件必须从索引的最左列开始,才能使用索引。

  9. aop 的原理

    AOP(面向切面编程):通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。其核心原理是将业务逻辑中的横切关注点(如日志、事务、安全等)抽象出来,形成切面。

    实现方式:在编译期,通过特殊编译器将切面代码织入到目标代码中;在运行期,通过动态代理(如 JDK 动态代理和 CGLIB 动态代理)动态生成代理对象,在代理对象中调用目标方法前后插入切面逻辑。

  10. bean 的作用域,如果单例 bean 来引用原型作用域,会发生什么问题,怎么解决

    Bean 作用域

    Singleton:在整个应用上下文中只有一个实例,默认作用域。

    Prototype:每次请求都会创建一个新的实例。

    问题:当单例 Bean 引用原型 Bean 时,由于单例 Bean 只在应用启动时创建一次,它引用的原型 Bean 也只会创建一次,无法实现原型 Bean 每次请求都创建新实例的特性。

    解决方法:可以通过方法注入的方式解决,即在单例 Bean 的方法中通过 ApplicationContext 获取原型 Bean 的新实例。

  11. 常用设计模式,应用场景,单例模式饿汉和懒汉,枚举类,双重检查锁防不了反射

    常用设计模式及应用场景

    单例模式:确保一个类只有一个实例,并提供全局访问点,如数据库连接池、线程池等。

    工厂模式:定义一个创建对象的接口,让子类决定实例化哪个类,适用于需要创建多种相关对象的场景,如 Spring 的 BeanFactory。

    观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新,如事件处理系统。

    单例模式实现方式

    饿汉式:在类加载时就创建实例,线程安全,但可能会造成资源浪费。

    懒汉式:在第一次使用时才创建实例,需要考虑线程安全问题,可以通过同步方法或双重检查锁实现。

    枚举类:通过枚举类型实现单例,线程安全且能防止反射攻击。

    双重检查锁:在懒汉式的基础上,通过双重检查减少同步的开销,但不能完全防止反射攻击。

  12. 缓存穿透,怎么处理

    缓存穿透:指查询一个一定不存在的数据,由于缓存中没有该数据,导致每次请求都直接访问数据库,给数据库带来很大压力。

    处理方法

    布隆过滤器:在缓存之前添加一个布隆过滤器,将所有可能存在的数据哈希到布隆过滤器中,查询时先在布隆过滤器中判断数据是否存在,不存在则直接返回,避免访问数据库。

    缓存空对象:对于查询不存在的数据,也在缓存中存储一个空对象,并设置较短的过期时间,这样再次查询时就可以从缓存中获取,减少数据库访问。

  13. 反问业务:传音控股有 4 条产品线,包括工厂(制造)、公司基础架构平台、供应商管理(营销,采购,财务)、售后,业务部规模 2 - 300 人。
二面问题解答
  1. 人在哪里,为什么现在才找工作:根据个人实际情况如实回答,如所在城市、之前的学习安排或职业规划调整等原因导致现在找工作。
  2. 常见的 web 安全问题,怎么防御

    SQL 注入:攻击者通过在输入中插入恶意 SQL 语句,窃取或篡改数据库数据。防御方法:使用预编译语句(PreparedStatement)、参数化查询,对用户输入进行过滤和验证。

    XSS 攻击:跨站脚本攻击,攻击者在网页中注入恶意脚本,当用户访问该网页时,脚本会在用户浏览器中执行,窃取用户信息。防御方法:对用户输入进行编码处理,使用内容安全策略(CSP)。

    CSRF 攻击:跨站请求伪造,攻击者诱导用户点击恶意链接,在用户不知情的情况下以用户身份发送请求。防御方法:使用 CSRF Token,验证请求来源。

  3. 介绍项目里面的 aop,通知方法有几种

    AOP 介绍:在项目中用于将横切关注点(如日志记录、事务管理)与业务逻辑分离,提高代码的可维护性和复用性。

    通知方法类型

    Before:在目标方法执行前执行。

    After:在目标方法执行后执行,无论方法是否抛出异常。

    AfterReturning:在目标方法正常执行完成后执行。

    AfterThrowing:在目标方法抛出异常后执行。

    Around:环绕通知,可以在目标方法执行前后执行自定义逻辑,是最强大的通知类型。

  4. 聊一下 ioc

    IOC(控制反转):是一种设计原则,将对象的创建、依赖注入等控制权从应用程序代码中转移到容器中。在 Spring 中,通过容器管理 Bean 的生命周期和依赖关系,降低了组件之间的耦合度,提高了代码的可维护性和可测试性。例如,通过配置文件或注解的方式将一个 Bean 注入到另一个 Bean 中,而不需要在代码中手动创建对象。

  5. hashmap 怎么存储数据,红黑树的高度是多少

    HashMap 存储数据:通过哈希函数将键映射为数组的索引,将键值对存储在数组的对应位置。如果发生哈希冲突,则使用链表或红黑树来解决冲突。

    红黑树高度:红黑树是一种近似平衡的二叉查找树,其高度最多为 2log(N + 1),其中 N 是树中节点的数量。

  6. hashmap 怎么保证分布均衡

    哈希函数设计:选择合适的哈希函数,尽量使键均匀分布到数组的各个位置,减少哈希冲突。

    扩容机制:当元素数量超过负载因子乘以初始容量时,进行扩容,重新计算元素的哈希值并分配到新的数组中,进一步保证分布均衡。

  7. 新建线程的方式

    继承 Thread 类:创建一个继承 Thread 类的子类,重写 run 方法,然后创建子类对象并调用 start 方法启动线程。

    实现 Runnable 接口:创建一个实现 Runnable 接口的类,实现 run 方法,将该类的对象作为参数创建 Thread 对象并调用 start 方法启动线程。

    实现 Callable 接口:与实现 Runnable 接口类似,但 Callable 接口的 run 方法可以有返回值,通过 FutureTask 和 Thread 来启动线程并获取返回值。

  8. 有一批任务执行完了汇总,怎么做;答 completefuture,面试官问计数器行不行,还有信号量

    CompleteFuture:可以使用 CompleteFuture 来异步执行任务,并通过链式调用组合多个任务,最后汇总结果。例如,使用 allOf 方法等待所有任务完成,然后获取每个任务的结果进行汇总。

    计数器:可以使用一个计数器来记录已完成的任务数量,当计数器达到任务总数时,进行结果汇总。但需要注意线程安全问题,可以使用原子类(如 AtomicInteger)来实现。

    信号量:信号量可以控制同时访问共享资源的线程数量。可以创建一个初始值为 0 的信号量,每个任务完成后释放一个信号量,主线程等待信号量数量达到任务总数时进行结果汇总。

  9. 课余比较系统学了 Java 的哪些部分:根据个人学习情况回答,如 Java 基础语法、面向对象编程、集合框架、多线程、IO/NIO、JVM 原理等。
  10. 学生成绩表,怎么计算所有学生的所有课程的总分,写 sql
SELECT student_id, SUM(score) AS total_scoreFROM student_scoresGROUP BY student_id;
  1. 如果课程没有分列,比如每个同学有 10 门课,就有 10 行数据,怎么实现上面的功能:上述 SQL 语句同样适用,它会自动按照学生 ID 分组并计算每个学生的所有课程总分。
  2. 除了考证,有没有参加学校活动,奖励:根据个人实际情况如实回答,如参加的社团活动、竞赛获奖情况等。
  3. 家在哪里,想在四川发展吗:根据个人意愿如实回答。
  4. 有没有参加导师的课题,平时时间安排怎么样,导师给的任务不多吗,你觉得这种工作强度怎么样:根据个人实际情况回答,如参加课题的情况、时间分配、对工作强度的感受等。
  5. 设计大型抽奖系统,考虑开放区间(谢谢参与)

    系统架构设计:采用分布式架构,将抽奖服务拆分为多个模块,如用户管理、奖品管理、抽奖逻辑、结果记录等,提高系统的可扩展性和性能。

    抽奖算法设计:可以使用随机数算法,根据奖品的概率分布生成随机数,确定用户是否中奖。对于开放区间(谢谢参与),可以设置一个较大的概率范围。

    并发处理:考虑高并发场景,使用线程池处理抽奖请求,避免系统过载。可以使用分布式锁保证奖品发放的原子性,防止超发。

    数据存储:使用数据库存储用户信息、奖品信息和抽奖结果,确保数据的持久化和一致性。可以使用缓存(如 Redis)提高系统的读取性能。

  6. 反问业务:校招有 2 - 3 个月的通识性培训,之后进行轮岗,大概半年,之后再定岗位,并且过半年可以自己申请换其他业务。