浩鲸科技面试
1 对java了解过什么,学习过程中有啥对你印象深刻的
答了数据结构,说了spring
spring不可变是为了什么?
2 hashmap底层实现
采用这种结构是为什么?
为什么会自动升级,有什么原因,好处
3 线程池了解过吗?说说线程池
8大参数问题
任务满了怎么办,等待队列问题
使用过程中遇到啥问题,还有一些记不得了
4 使用锁的时候遇到了什么问题
答了个共享区数据原子性问题
5 缓存穿透问题
布隆穿透器实现原理
6 syc锁reen锁区别
还有一些零零散散的问题
7 threadlocal实现原理
8 mybatis实现原理
9 spring实现原理
bean初始化
注解有哪些
10 springboot注解
与spring区别
11 人员权限怎么分配解决
12 反问
13 建议了解原理,知道为什么用,解决了什么
面试官人好好,去的太早,在午休还特意下楼一起转了一圈再上来面试。奈何自己太菜了,凉凉😭 #面试交流地#
答了数据结构,说了spring
spring不可变是为了什么?
2 hashmap底层实现
采用这种结构是为什么?
为什么会自动升级,有什么原因,好处
3 线程池了解过吗?说说线程池
8大参数问题
任务满了怎么办,等待队列问题
使用过程中遇到啥问题,还有一些记不得了
4 使用锁的时候遇到了什么问题
答了个共享区数据原子性问题
5 缓存穿透问题
布隆穿透器实现原理
6 syc锁reen锁区别
还有一些零零散散的问题
7 threadlocal实现原理
8 mybatis实现原理
9 spring实现原理
bean初始化
注解有哪些
10 springboot注解
与spring区别
11 人员权限怎么分配解决
12 反问
13 建议了解原理,知道为什么用,解决了什么
面试官人好好,去的太早,在午休还特意下楼一起转了一圈再上来面试。奈何自己太菜了,凉凉😭 #面试交流地#
全部评论
是日常实习吗🤔
佬是在哪里投的,我官网上只找到了管培生招聘
get
外包都这么难?
我连简历都没过😭
难度过大,当面着刷感觉了
string还是spring
日常实习是多少米一天啊
佬,这个2自动升级是啥,求解答😂
你是广工大四的吗?我也是广工的,现在浩鲸做前端实习
1. 对java了解过什么,学习过程中有啥对你印象深刻的
- 数据结构方面
- Java中的数据结构包括数组、链表、栈、队列、树(二叉树、红黑树等)、图、哈希表(如HashMap底层使用的哈希表结构)等。这些数据结构在不同的场景下有不同的应用。例如,数组适合随机访问,链表适合动态插入和删除操作。
- Spring相关
- Spring是一个开源的Java应用框架,它提供了很多功能,如依赖注入(DI)和面向切面编程(AOP)。它简化了Java企业级应用的开发,通过配置文件或注解的方式来管理对象之间的依赖关系,提高了代码的可维护性和可扩展性。
2. spring不可变是为了什么?
- 在Spring中,一些对象被设计为不可变的主要原因包括:
- 线程安全:不可变对象在多线程环境下是线程安全的,不需要额外的同步机制来保证数据的一致性。多个线程可以同时访问不可变对象,不会出现数据竞争和不一致的情况。
- 简化设计和维护:不可变对象的状态一旦确定就不能改变,这使得对象的行为更加可预测。在设计和维护大型系统时,更容易理解和推理对象的行为,减少了由于对象状态变化而带来的复杂性和错误。
- 缓存友好:不可变对象可以被安全地缓存,因为它们的值不会改变。这可以提高应用程序的性能,尤其是在频繁使用某些对象的情况下。
3. hashmap底层实现
- 结构基础
- HashMap底层是基于数组和链表(在Java 8中,当链表长度达到一定阈值时会转换为红黑树)实现的。它使用哈希函数将键(key)映射到数组的一个索引位置上,以实现快速的查找、插入和删除操作。
- 采用这种结构的原因
- 快速查找:通过哈希函数计算键的哈希值,可以快速定位到数组中的一个位置,平均情况下查找时间复杂度接近O(1)。如果没有哈希冲突(即不同的键计算出相同的哈希值),查找操作可以非常迅速。
- 动态扩展:数组可以根据需要动态扩展,以适应不断增加的键值对数量。当数组中的元素数量达到一定阈值时,会进行扩容操作,重新分配内存空间并重新计算键的哈希值,以保证哈希表的性能。
- 自动升级(Java 8中链表转红黑树)的原因和好处
- 原因
- 当链表过长时,查找操作的时间复杂度会退化为O(n),其中n是链表的长度。为了避免这种情况,当链表长度达到一定阈值(默认为8)且数组长度达到一定条件时,链表会转换为红黑树。
- 好处
- 红黑树是一种自平衡的二叉搜索树,它可以保证查找、插入和删除操作的时间复杂度在最坏情况下仍然是O(log n),大大提高了在哈希冲突较多情况下的查找性能。
4. 线程池了解过吗?说说线程池
- 概念和作用
- 线程池是一种用于管理和复用线程的机制。它预先创建一定数量的线程,并将这些线程保存在一个池中,当有任务需要执行时,从线程池中获取一个空闲的线程来执行任务,任务执行完成后,线程不会被销毁,而是返回线程池中等待下一个任务。这样可以避免频繁地创建和销毁线程,提高系统的性能和资源利用率。
- 8大参数问题
- 核心线程数(corePoolSize):线程池中的核心线程数量,这些线程即使在空闲状态也不会被销毁。
- 最大线程数(maximumPoolSize):线程池允许创建的最大线程数量,当任务队列已满且核心线程都在忙碌时,会创建新的线程直到达到最大线程数。
- 线程存活时间(keepAliveTime):当线程池中的线程数量超过核心线程数时,多余的线程在空闲状态下的存活时间。
- 时间单位(unit):用于指定线程存活时间的单位,如秒、分钟等。
- 任务队列(workQueue):用于存储等待执行的任务的队列。常见的任务队列有ArrayBlockingQueue(有界队列)、LinkedBlockingQueue(无界队列,默认容量为Integer.MAX_VALUE)、SynchronousQueue(同步队列,不存储任务,直接将任务交给线程执行)等。
- 线程工厂(threadFactory):用于创建新线程的工厂类,可以自定义线程的名称、优先级等属性。
- 拒绝策略(handler):当线程池和任务队列都已满,无法再接受新的任务时所采取的策略。常见的拒绝策略有AbortPolicy(直接抛出异常)、CallerRunsPolicy(由调用者所在的线程执行任务)、DiscardPolicy(直接丢弃任务)、DiscardOldestPolicy(丢弃任务队列中最旧的任务)等。
- 任务满了怎么办,等待队列问题
- 当任务队列已满且线程池中的线程数量达到最大线程数时,会根据所采用的拒绝策略来处理新的任务。如果是AbortPolicy,会直接抛出异常;如果是CallerRunsPolicy,由调用者所在的线程执行任务;如果是DiscardPolicy,直接丢弃任务;如果是DiscardOldestPolicy,丢弃任务队列中最旧的任务。
5. 使用锁的时候遇到了什么问题
- 共享区数据原子性问题(以常见的情况为例)
- 当多个线程同时访问和修改共享区域的数据时,如果没有合适的锁机制,可能会出现数据不一致的情况。例如,两个线程同时对一个计数器进行加1操作,如果没有锁,可能会出现两个线程同时读取到相同的计数器值,然后各自加1,最终计数器只增加了1,而不是预期的2。使用锁可以保证在同一时刻只有一个线程能够访问和修改共享数据,从而保证数据的原子性和一致性。
6. 缓存穿透问题
- 概念
- 缓存穿透是指查询一个不存在的数据,由于缓存中没有该数据,所以会去数据库中查询。如果大量这样的请求同时发生,会给数据库带来很大的压力,甚至可能导致数据库崩溃。
- 布隆穿透器实现原理
- 布隆过滤器是一种数据结构,它由一个位数组和多个哈希函数组成。当一个数据要被判断是否存在时,会使用多个哈希函数对该数据进行哈希运算,得到多个哈希值,然后根据这些哈希值在位数组中查找相应的位置。如果所有位置都被标记为存在,那么该数据可能存在;如果有任何一个位置被标记为不存在,那么该数据一定不存在。这样可以在一定程度上避免缓存穿透,因为它可以快速判断一个数据是否可能存在于缓存中,而不需要每次都去数据库查询。
7. syc锁reen锁区别
- 我不确定这里“syc锁reen锁”是否是“synchronized锁和ReentrantLock锁”的错误表述,如果是,它们的区别如下:
- synchronized锁
- 是Java中的内置锁机制,它是一种隐式锁,通过在方法或代码块前加上synchronized关键字来实现。它具有以下特点:
- 简单易用:不需要显式地获取和释放锁,由Java虚拟机自动管理锁的获取和释放过程。
- 可重入性:一个线程可以多次获取同一个synchronized锁,不会造成死锁。例如,一个线程在进入一个synchronized方法后,如果在方法内部又调用了另一个synchronized方法,它可以再次获取到锁。
- 局限性:
- 不够灵活,无法设置锁的获取和释放的条件。
- 性能方面在一些高并发场景下可能不如ReentrantLock。
- ReentrantLock锁
- 是Java中的一种显式锁,它需要通过lock()方法获取锁,通过unlock()方法释放锁。它具有以下特点:
- 灵活性:可以设置公平锁和非公平锁。公平锁是指按照线程请求锁的先后顺序来获取锁,非公平锁则不保证线程获取锁的顺序。
- 可重入性:同样具有可重入性,一个线程可以多次获取同一个ReentrantLock锁。
- 性能优势:在一些高并发场景下,通过合理设置锁的参数和使用方式,可以获得更好的性能。
- 缺点:
- 需要显式地获取和释放锁,如果忘记释放锁会导致死锁。
8. threadlocal实现原理
- ThreadLocal是Java中的一个类,它用于在每个线程中提供一个独立的变量副本。其实现原理如下:
- 内部结构
- ThreadLocal内部维护了一个静态的内部类ThreadLocalMap,它类似于一个哈希表,用于存储每个线程的变量副本。
- 存储过程
- 当一个线程第一次访问一个ThreadLocal变量时,会在ThreadLocalMap中创建一个新的键值对,键为当前线程对象,值为该ThreadLocal变量的初始值(如果有指定)。此后,该线程每次访问这个ThreadLocal变量时,都会从ThreadLocalMap中获取对应的键值对,从而保证每个线程都能获取到自己独立的变量副本。
- 内存管理
- ThreadLocalMap中的键值对是通过弱引用(WeakReference)来维护的。这意味着当一个线程结束或者不再需要某个ThreadLocal变量时,垃圾回收器可以更方便地回收这些键值对所占用的内存,避免内存泄漏。
9. mybatis实现原理
- MyBatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。它的实现原理如下:
- 配置文件和映射文件
- MyBatis通过配置文件和映射文件来管理数据库连接、SQL语句和对象映射关系。配置文件中包含了数据库连接信息、全局配置参数等,映射文件则针对每个实体类和数据库表,定义了SQL语句和对象映射的细节。
- 动态代理
- MyBatis使用动态代理技术来生成针对接口的代理对象。当调用接口中的方法时,代理对象会根据方法名和参数等信息,在映射文件中查找对应的SQL语句,并执行SQL查询或更新操作,然后将结果映射回实体类对象。
- 结果映射
- 在执行SQL操作后,MyBatis会根据映射文件中的结果映射规则,将查询结果中的数据转换为实体类对象。这可能涉及到字段名和属性名的匹配、数据类型的转换等操作。
10. spring实现原理
- 核心概念
- Spring的核心是依赖注入(DI)和面向切面编程(AOP)。
- 依赖注入原理
- Spring通过配置文件或注解的方式来管理对象之间的依赖关系。在运行时,Spring会根据配置信息,将依赖的对象注入到需要的对象中。例如,如果一个Service类依赖于一个Dao类,Spring会在创建Service类对象时,将Dao类对象注入到Service类中。
- 面向切面编程原理
- AOP是一种编程范式,它通过分离横切关注点(如日志记录、事务管理等)来提高代码的可维护性和可扩展性。Spring通过动态代理或字节码增强等技术来实现AOP。例如,在一个业务方法执行前后,通过AOP可以自动插入日志记录或事务管理的代码,而不需要在每个业务方法中都手动添加这些代码。
- bean初始化
- Spring中的bean初始化过程包括以下几个主要步骤:
- 创建对象:根据配置信息或注解,通过反射机制创建bean对象。
- 属性注入:将依赖的对象注入到bean对象中,如前面提到的依赖注入原理。
- 调用初始化方法:如果bean对象定义了初始化方法,Spring会在对象创建和属性注入完成后,调用这个初始化方法。
- 注解有哪些
- Spring中有很多注解,常见的包括:
- @Component:用于标识一个普通的组件类,可以被Spring容器扫描并管理。
- @Service:用于标识一个服务类,通常是业务逻辑层的类。
- @Repository:用于标识一个数据访问层的类,通常用于与数据库交互。
- @Controller:用于标识一个控制器类,通常用于处理Web请求。
- @Autowired:用于自动注入依赖对象。
- @Qualifier:用于指定注入对象的具体名称或类型,与@Autowired配合使用。
- @Value:用于注入配置文件中的值。
11. springboot注解
- Spring Boot是在Spring基础上发展起来的,它简化了Spring应用的开发和部署。Spring Boot中有很多注解,常见的包括:
- @SpringBootApplication:这是一个组合注解,它包含了@Configuration、@EnableAutoConfiguration和@SpringBootWebApplicationContext等注解的功能。它用于标记一个Spring Boot应用的主类,启动Spring Boot应用时,会从这个主类开始扫描和加载相关的组件。
- @Configuration:用于标识一个配置类,在这个类中可以定义各种配置方法,如定义Bean对象、配置数据源等。
- @EnableAutoConfiguration:它会根据类路径上的现有资源和配置信息,自动配置Spring Boot应用所需的各种组件,如数据库连接、Web服务器等。
- @RestController:这是一个组合注解,它包含了@Controller和@RestService的功能。用于标识一个控制器类,并且这个类中的方法返回值会直接作为JSON格式的数据发送出去,适合用于构建RESTful API。
- @RequestMapping:用于定义一个请求路径,当客户端发出的请求路径与这个定义的路径匹配时,会执行相应的方法。
- 与spring区别
- 配置方式:Spring Boot简化了Spring的配置方式。Spring通常需要大量的配置文件和注解来管理对象之间的依赖关系和各种应用组件,而Spring Boot通过自动配置和约定大于配置的原则,大大减少了配置的工作量。
- 启动方式:Spring Boot有自己独特的启动方式,通过@SpringBootApplication注解标记的主类,使用main方法即可启动应用。而Spring需要更多的手动配置和启动步骤。
- 应用场景:Spring Boot更适合快速开发和部署小型到中型的应用,它提供了一站式的解决方案,包括内置的服务器、自动配置等。Spring则更适合用于大型企业级应用的开发,它提供了更强大的功能和更灵活的配置方式,需要开发者有更高的技能水平和更多的时间来进行配置和维护。
相关推荐