导购网站开发要多少钱,室内设计作品,网站开发加盟商怎么做,泰安seo外包公司文章目录 引言正文面经整理一1、讲一下java的多态#xff0c;重载#xff0c;重写的概念#xff0c;区别2、说一下Java的数组#xff0c;链表的结构#xff0c;优缺点3、创建java线程的方式有哪些#xff0c;具体说说4、创建线程池呢、每个参数的意义5、通过那几种方式保… 文章目录 引言正文面经整理一1、讲一下java的多态重载重写的概念区别2、说一下Java的数组链表的结构优缺点3、创建java线程的方式有哪些具体说说4、创建线程池呢、每个参数的意义5、通过那几种方式保证线程安全6、jvm加载7、了解数据库事物特性8、怎么提高sql查询性能 只说了添加索引分库分表9、String特性是什么10、redis数据类型11、redis持久化 答了AOFRDB接着问了他们之间的区别 面经整理二1、spring是怎么实现aop的2、aop的原理3、用户通过客户端或者浏览器发送请求在springboot框架下是如何接收这个请求、解析并向下透传到control层的4、mysql的底层结构5、索引分为哪几个类型6、以非聚簇索引作为一个查询条件去获取到整条记录的中间过程是什么7、建索引要满足哪些原则8、hashmap扩容的过程9、synchronized和可重入锁有哪些区别10、线程安全的集合concurrenthashmap是如何保证线程安全的11、java的内存分布12、1.8的jvm默认的两个垃圾回收器是哪两个区别是什么13、有一个web服务的接口刚上线的时候没有什么问题突然一段时间后客户端调用该接口该接口的反馈都是超时如何定位这个服务的问题 正式面试第一面A面B面ThreadLocal了解吗如何防止内存泄漏如何对复杂对象进行深拷贝SpringAOP的实现过程 笔试总结 引言
今天要面试万得数据上午在整理项目相关的问题看相关的代码现在整理一下面经毕竟下午两点钟就要开始的
正文
面经整理一
作者网抑云八级选手 链接https://www.nowcoder.com/feed/main/detail/a44af7a275754bc0a200fcc9778d64c0?sourceSSRsearch 来源牛客网
1、讲一下java的多态重载重写的概念区别
多态
同一个接口或者基类可以指向不同的实现或子类对象编写更加通用和灵活的代码 编译时多态静态多态通过方法重载实现。运行时多态动态多态通过方法重写和接口实现。
重载
重载是指在同一个类中可以有多个同名的方法但它们的参数列表不同参数的数量或类型不同。重载是编译时多态的一种形式。主要特点 方法名相同。参数列表不同参数的数量或类型不同。可以有不同的返回类型。可以有不同的访问修饰符。
重写
重写是指子类提供了与父类中同名方法的实现。重写是运行时多态的一种形式。通过重写子类可以提供特定的实现而不是使用父类的实现。主要特点 方法名、参数列表、返回类型必须相同。访问修饰符不能比父类的更严格可以更宽松。子类方法不能比父类方法抛出更多或更广泛的异常。
区别
多态同一个接口或者基类可以多种实现重载在同一个类中同名方法有不同的参数列表是编译时多态重写子类提供与父类同名方法的实现运行时多态
2、说一下Java的数组链表的结构优缺点
数组
一种线性数据结构用于存储相同类型元素的集合。数组在内存中是连续分配的所有元素的大小相同可以通过索引快速访问。优点 快速访问由于数组元素在内存中是连续存储的可以通过索引在O(1)时间复杂度内直接访问任意元素。节省内存没有额外的存储开销如指针。缓存友好由于数组元素连续存储使用缓存时效率更高。 缺点 固定大小数组的大小在创建时必须确定之后不能改变。这可能导致内存浪费或不够用。插入和删除效率低在数组中插入或删除元素需要移动大量元素时间复杂度为O(n)。不适合频繁插入和删除操作由于上述原因数组不适合在中间频繁进行插入和删除操作。
链表 一种线性数据结构由一系列节点Node组成每个节点包含数据和指向下一个节点的引用或指针 根据节点之间的连接方式链表可以分为单向链表Singly Linked List和双向链表Doubly Linked List 优点 动态大小链表可以根据需要动态增长或缩小不需要预先分配固定大小。插入和删除操作高效在链表中插入或删除元素不需要移动其他元素只需修改指针即可时间复杂度为O(1)在已知位置的情况下。适用于频繁插入和删除操作尤其是在中间插入或删除时链表比数组更高效。 缺点 访问速度慢由于无法通过索引直接访问元素必须从头节点开始逐个遍历时间复杂度为O(n)。额外的内存开销每个节点除了存储数据还需要存储指针这会占用额外的内存。缓存不友好由于链表元素在内存中不是连续存储的使用缓存时效率较低。
3、创建java线程的方式有哪些具体说说
继承Thread类
结构 通过继承Thread类并重写run方法来创建线程。 步骤 创建一个继承自Thread类的子类。在子类中重写run方法将线程的执行逻辑写在run方法中。创建该子类的实例并调用start方法启动线程。
实现Runnable接口 结构 通过实现Runnable接口并将其传递给Thread类来创建线程。 步骤 创建一个实现Runnable接口的类。在类中实现run方法将线程的执行逻辑写在run方法中。创建该类的实例并将其作为参数传递给Thread对象。调用Thread对象的start方法启动线程。
。。。
总结
继承Thread类简单直接但不支持多继承。实现Runnable接口推荐使用符合Java单继承多实现的特性。使用Callable和Future适用于需要返回结果或抛出异常的任务。使用ExecutorService框架适用于需要高效管理线程池的场景。
4、创建线程池呢、每个参数的意义
5、通过那几种方式保证线程安全
6、jvm加载
7、了解数据库事物特性
8、怎么提高sql查询性能 只说了添加索引分库分表 优化查询语句 避免SELECT *尽量只查询需要的列使用WHERE条件筛选数据减少返回的数据量避免在WHERE子句中使用函数使用函数会导致无法使用索引从而降低查询性能。 索引优化 创建合适的索引使用覆盖索引 数据库分区 使用分区表将大表按照某个字段如日期、ID范围进行分区减少单个分区的数据量提高查询性能。 数据库配置优化 调整数据库配置根据实际需求调整数据库的内存分配、缓存大小、连接数等配置参数提高整体性能。
9、String特性是什么
不可变性Immutability
在Java中String对象是不可变的。一旦创建字符串的值就不能更改。如果需要修改字符串则会创建一个新的字符串对象。
字符串池String Pool
Java使用字符串池来优化字符串的存储和管理。当你创建一个字符串字面量时JVM会先检查字符串池中是否存在相同的字符串。如果存在则返回对该字符串的引用如果不存在则在池中创建新的字符串。
字符串连接Concatenation
Java支持使用操作符进行字符串连接也可以使用StringBuilder或StringBuffer来提高性能。StringBuilder和StringBuffer是可变的并且提供了对字符串的高效修改操作。
10、redis数据类型
11、redis持久化 答了AOFRDB接着问了他们之间的区别
面经整理二
作者MO小天才 链接https://www.nowcoder.com/feed/main/detail/363997511497459ea21b12aa686439d7?sourceSSRsearch 来源牛客网
1、spring是怎么实现aop的 一种用于分离关注点的技术特别是在横切关注点如日志记录、事务管理、权限控制等方面。Spring AOP的实现主要基于代理模式。 切面Aspect 切面是横切关注点的模块化表现是通知advice和切入点pointcut的结合。 通知Advice 通知是在切入点上执行的操作。常见的通知类型包括前置通知before、后置通知after、返回通知after returning、异常通知after throwing和环绕通知around。 切入点Pointcut 切入点定义了通知应当应用到哪些连接点Join Points。通常使用AspectJ表达式语言来定义切入点。 目标对象Target Object 目标对象是被通知的对象即那些包含核心业务逻辑的方法被AOP框架拦截的对象。 代理Proxy 代理是AOP框架创建的对象它被用来代替目标对象。代理对象负责拦截方法调用并在适当的时间执行通知。 织入Weaving 织入是将切面应用到目标对象并创建代理对象的过程。Spring AOP在运行时通过动态代理或CGLIB代理进行织入。
2、aop的原理
Spring AOP通过动态代理JDK动态代理和CGLIB代理实现了AOP的功能使得我们可以在不修改业务代码的情况下将横切关注点如日志记录、事务管理等应用到目标对象的方法上。
3、用户通过客户端或者浏览器发送请求在springboot框架下是如何接收这个请求、解析并向下透传到control层的
1、接收请求
当用户发送HTTP请求时嵌入式服务器会受到请求
2、请求解析
将请求传递给Servlet容器进行解析变成HttpServletRequest和HttpServletResponse对象
3、拦截请求
DispatcherServlet它是Spring MVC的前端控制器负责处理所有进来的HTTP请求。映射到所有路径/因此它会拦截所有请求。
4、映射控制器
会根据请求的URL和HTTP方法GET、POST等通过HandlerMapping找到相应的处理器HandlerMapping的工作是将请求映射到具体的控制器类和方法上。
5、调用控制器方法
DispatcherServlet会使用HandlerAdapter调用控制器方法。 控制器方法通常使用RequestMapping或其他映射注解如GetMapping、PostMapping等来指定URL路径和请求方法。
6、处理请求并返回响应对象
控制器方法处理请求并返回一个响应对象一般是调用service层的处理业务逻辑并将结果返回
7、返回给客户端
响应返回给Servlet容器Servlet容器将响应发送回客户端
4、mysql的底层结构
5、索引分为哪几个类型
6、以非聚簇索引作为一个查询条件去获取到整条记录的中间过程是什么
1. 在非聚簇索引中查找键值
查找索引键、 数据库引擎在非聚簇索引的 B 树中查找符合查询条件的索引键。 获取聚簇索引键 找到匹配的索引键后获取指向实际数据记录的指针或聚簇索引键值。
2. 在聚簇索引中查找完整记录
查找数据记录 使用从非聚簇索引中获取的聚簇索引键值在聚簇索引的 B 树中查找完整的数据记录。 返回完整记录 找到对应的叶节点后提取并返回完整的数据记录。
7、建索引要满足哪些原则
8、hashmap扩容的过程
触发条件
容量capacityHashMap桶bucket数组的当前大小。负载因子load factor当HashMap的元素数量超过capacity * load factor时触发扩容。默认负载因子为0.75。
扩容过程 a. 计算新容量 HashMap扩容时新容量通常是旧容量的两倍。扩容后新容量和新阈值会重新计算。 b. 创建新桶数组 创建一个大小为新容量的新的桶数组 c.重新分配元素 将旧桶数组中的所有元素重新计算哈希并分配到新桶数组中。由于容量的变化元素的位置可能会发生变化。链表节点重新分配旧桶数组中存在链表时需要对链表节点重新分配。根据节点的哈希值决定其在新桶数组中的位置。如果节点的哈希值与旧容量进行按位与运算结果为0则其放置在新桶中的原位置否则放置在原位置加上旧容量的位置。 更新HashMap的引用和阈值 将HashMap的桶数组引用更新为新的桶数组并更新阈值。
9、synchronized和可重入锁有哪些区别
10、线程安全的集合concurrenthashmap是如何保证线程安全的
分段锁 减少锁争用提高并发性能。 CAS 操作和自旋锁 保证原子性和线程安全。 细粒度锁 对每个桶进行锁定允许更多并发操作。 树化和链化 提高哈希冲突处理效率每一个桶的链表长度超过阈值转为红黑树提高查找和出入效率 无锁读操作 提高并发读性能。 高效扩容 分批次进行扩容减少性能影响。
11、java的内存分布
堆Heap存储所有对象实例和数组分为年轻代和老年代。栈Stack每个线程都有自己的栈存储局部变量、方法调用等信息。方法区Method Area存储类的元数据、静态变量、常量池等。在Java 8之后称为元空间Metaspace。程序计数器PC Register指示当前线程执行的字节码位置。本地方法栈Native Method Stack为虚拟机执行本地方法服务。
12、1.8的jvm默认的两个垃圾回收器是哪两个区别是什么 1. Parallel GC并行垃圾回收器 特点 年轻代收集使用多线程的复制算法copying。老年代收集使用多线程的标记-压缩算法mark-compact。多线程使用多个线程同时进行垃圾回收操作适用于多核 CPU提高垃圾回收效率。吞吐量优先Parallel GC 设计的目标是最大化吞吐量最小化垃圾回收对应用程序的影响时间。 2. G1 GCGarbage-First Garbage Collector 特点 分区将整个堆内存划分为多个相等大小的独立区域Region每个区域可以充当 Eden、Survivor 或 Old 区。混合收集年轻代和老年代一起进行收集mixed collection在一次垃圾回收过程中既回收年轻代又回收部分老年代。并发标记G1 GC 使用并发标记阶段来标记存活对象从而减少应用程序暂停时间。停顿时间目标允许用户指定期望的停顿时间通过调优停顿时间目标来满足应用程序的低延迟要求。
13、有一个web服务的接口刚上线的时候没有什么问题突然一段时间后客户端调用该接口该接口的反馈都是超时如何定位这个服务的问题
1. 检查服务器资源2. 检查应用日志3. 检查数据库性能 慢查询连接池耗尽锁争用 4、检查外部依赖是否正常 缓存服务器消息队列 5、分析网络问题 网络延迟防火墙和负载均衡器 6、重现问题 尝试在本地或者测试环境中重现则个问题以便更容易调试和分析
正式面试
第一面
A面 1、重点介绍一下个人项目 说的过于琐碎没有必要需要概括一下重点说出你的要点而不是很细致地完全讲出来没有必要重点介绍Java相关的项目 2、浮点数了解吗怎么实现的 浮点数的实现主要是基于科学计数法有以下四部分构成分别是 符号位0正数1负数基数:使用二进制表示指数表示基数应该乘以多少次幂可以是正数或者负数尾数有效位数 特殊 不能表示所有数字涉及小数比较时需要处理小数误差正零和负零无穷大超出表示范围的数字NaN未定义或者不确定地结果 3、给你一个数组数组里面全部是数字然后再给你一个s表示窗口的大小从最左侧滑动然后滑动到最右侧求取每一次移动的滑动窗口平均值你计算一下滑动窗口的最小值并计算一下的时间复杂度和空间复杂度 想不出更好的做法只能使用模拟的方式实现维护滑动窗口的sum然后每一次计算一次平均值比较平均值的最最优值。时间复杂度是O(n)空间复杂度是O(1).
B面 1、简单的自我介绍 项目介绍太过繁琐很多细节不需要只需要说你做了什么项目大概概括一下项目就说做了什么然后你有哪些工作然后总结一下没有必要面面俱到什么都说。 项目上线了吗 并没有上线在等进一步审核。 系统的准确率是多少 分情况说比较真实。 针对这种情况有什么其他的优化方案吗 拓宽信息模态更换信息收集场景 这个项目是基于大语言模型的谁在维护和训练 使用开源大语言模型的API直接调用的并没有的自己训练一个大语言模型 说一下ThreadLocal的使用怎么防止内存泄露 ThreadLocal是的key是弱引用但是他的value会强引用通过调用对应的set等方法会自动回收不再使用value但是线程不再被使用不再调用对应方法就不会进行内存回收导致内存泄漏如何避免内存泄漏 先获取到 ThreadLocalMap 这个引用的并且调用了它的 remove 方法手动调用remove方法防止内存泄漏 MySQL中聚簇索引和非聚簇索引有什么区别 聚簇索引 聚簇索引决定了磁盘上的存储顺序同时聚簇索引的叶子节点包含了完整的数据行查询聚簇索引无需额外查询数据主键默认创建为聚簇索引如果没有指定主键会选择一个唯一非空索引作为聚簇缩影。 非聚簇索引 非聚簇索引是单独的索引结构叶子节点不包含数据行而是包含了指向数据行的指针非聚簇索引和数据的存储顺序无关非聚簇索引的叶子节存储的是数据行的位置或者主键位置通常需要二次查找。 建表的时候没有指定任何列作为他的主键会创建的主键索引吗 首先检查表中是否存在唯一非空的索引有就将其作为主键索引然后如果表中没有主键没有唯一索引自动生成一个6字节长的隐藏主键列不可见无法访问 InnoDB引擎默认的隔离级别是什么这个隔离级别会带来问题做了哪些操作来尽量缓解这个问题 可重复读解决了脏读和不可重读但是还是存在部分幻读如何解决幻读的问题 提供了两种查询方式的分别是快照读和当前读都会产生幻读针对快照读使用MVCC来解决幻读问题第一次查询生成一个readview然后在当前事务中都使用相同的readview保证结果相同。针对当前读依靠行级锁中的间隙锁来实现但并不能完全避免一般是没有加上对应的for update SpringAOP的实现过程 用于在不修改代码的情况下动态地将某些行为应用到特定的方法或者类上。主要是基于动态代理和字节码操作实现。定义一个切面类这个切面类中要指明增强的方式是Before还是AfterReturning等同时指定对应地切点然后定义具体的需要额外执行的逻辑和行为。主要是定义通知类和配置类具体编程实现如下 第二阶段会有一个算法题HR会通知你的。
ThreadLocal了解吗如何防止内存泄漏
资料来源 ThreadLocal介绍
应用场景 ThreadLocal用作保存每一个线程独享的对象每一个线程都创建一个副本这样每一个线程都可以修改自己所拥有的副本不会影响其他线程的副本确保线程安全 保存线程不安全的工具类典型需要使用的类是SimpleDataFormat ThreadLocal 用作每一个线程内需要独立保存信息以便供线程内其他方法更方便地获取该信息场景。线程内每个方法获取到的信息是不一样的前面执行的方法保存了信息后后续方法可以通过ThreadLocal获取避免传参类似线程内的全局变量。保存业务的一些内容比如说在拦截器中获取用户的信息可以让不同方法直接使用避免了传递参数麻烦 ThreadLocal可以用来解决共享资源的多线程访问的问题吗
不是ThreadLocal 并不是用来解决共享资源问题的。虽然 ThreadLocal 确实可以用于解决多线程情况下的线程安全问题但其资源并不是共享的而是每个线程独享的。
ThreadLocal和Synchronized关系
ThreadLocal 是通过让每个线程独享自己的副本避免了资源的竞争。synchronized 主要用于临界资源的分配在同一时刻限制最多只有一个线程能访问该资源。
ThreadLocal、Thread和ThreadLocalMap的关系
一个Thread有一个ThreadLocalMap而ThreadLocalMap的key就是一个一个ThreadLocal
防止内存泄漏
内存泄漏 当某一个对象不在有用时占用的内存却不能被回收是内存泄漏 引用分析 ThreadLocal中的key是弱引用如果不在引用了垃圾回收机制能够成功收回ThreadLocal中value是强引用如果某一个Thread长时间运行并且某一个Thread不再被使用那么这个value就会内存泄漏没法被垃圾回收 set、remove和rehash都会刷新key-value如果key为null会自动回收对应的value但是如果不调用就没有办法刷新了 如何避免内存泄漏 先获取到 ThreadLocalMap 这个引用的并且调用了它的 remove 方法手动调用remove方法防止内存泄漏
如何对复杂对象进行深拷贝
实现 Cloneable 接口并重写 clone() 方法 通过实现 Cloneable 接口并重写 clone() 方法可以对对象进行深拷贝 使用序列化进行深拷贝 通过将对象序列化为字节流然后反序列化可以实现深拷贝。 递归实现深拷贝 通过自定义的递归方法我们可以实现对复杂对象的深拷贝。此方法适用于对象嵌套结构较为复杂的情况。
SpringAOP的实现过程 一种用于分离关注点的技术特别是在横切关注点如日志记录、事务管理、权限控制等方面。Spring AOP的实现主要基于代理模式。 切面Aspect 切面是横切关注点的模块化表现是通知advice和切入点pointcut的结合。 通知Advice 通知是在切入点上执行的操作。常见的通知类型包括前置通知before、后置通知after、返回通知after returning、异常通知after throwing和环绕通知around。 切入点Pointcut 切入点定义了通知应当应用到哪些连接点Join Points。通常使用AspectJ表达式语言来定义切入点。 目标对象Target Object 目标对象是被通知的对象即那些包含核心业务逻辑的方法被AOP框架拦截的对象。 代理Proxy 代理是AOP框架创建的对象它被用来代替目标对象。代理对象负责拦截方法调用并在适当的时间执行通知。 织入Weaving 织入是将切面应用到目标对象并创建代理对象的过程。Spring AOP在运行时通过动态代理或CGLIB代理进行织入。 Spring AOP通过动态代理JDK动态代理和CGLIB代理实现了AOP的功能使得我们可以在不修改业务代码的情况下将横切关注点如日志记录、事务管理等应用到目标对象的方法上。
笔试
对于必胜的理解
对于序列a而言其中的元素[a1,a2,a3,a4,a5]等要是必赢的情况下随便取出来一个数字ax使得剩下元素的最大值amax和amin的累加和 大于等于 target但是最大值不能大于等于target只要能够是这种情况那么先手肯定是必胜的。如果是这种只能够报数三次的情况肯定能够判定出来的。当前方选什么才能让后方必输但是如果当前报数并不能立刻判定出能否获胜的话就不好判定了
A和B都会按照最优的方式报数
如果轮到A只要A能够赢或者说存在必赢的方案一定会选择必赢的方案如果轮到B只要B能够赢或者说存在必赢的方案一定会选择必赢的方案言外之意就是A每一次做出决定之前都要判定会不会给B带来必赢的局面如果能够给B带来必赢的局面就不选当前方案
能否通过动态规划实现
如果使用动态规划实现必须能够使用集合的语言进行表达但是这个题目不知道怎么用集合的语言表达。我应该还是会使用回溯实现
回溯条件
如果无论A选什么B都存在必胜的条件那么就返回false如果无论A选了某个分支B无论选了什么那么就返回true
具体实现代码
import java.io.FilterOutputStream;
import java.util.*;/*** author Long Guo* create 2024-08-10-14:32*///TIP To bRun/b code, press shortcut actionIdRun/ or
// click the icon srcAllIcons.Actions.Execute/ icon in the gutter.
public class Main {// 定义不同的状态表示当前是谁在报数static boolean A true;static boolean B false;static ListInteger list; // 能够报的数字的列表static MapInteger, Boolean cached;static boolean dfs(int target, boolean AorB, int cacheNum) {/** 具体含义当前做选择的游戏玩家是否存在胜利的情况存在返回true不存在返回false* list表示剩余列表中所有能够选择的数字* target表示目标数值* AorB表示对应的角色true表示为A先手false表示B后手* 基本思路* 在所有搜索树中总共有两种选择关系分别是的由A到B和由B到A* A选B一旦所有B的情况中有一种是B必胜的情况那么就不能选因为B一定会选必胜的情况所以这里需要的将所有B可选的情况通过与进行连接* B选A一旦所有的A的情况中有一种的A必胜的情况B就不会选所以这里要选择全部是false的情况也就是通过或进行连接全部为false的情况* 最终通过回溯判定当前节点下是否存在A必胜的情况*/// 临界条件必赢状况这里需要特殊处理如果是B的回合那就是A必输的情况int m list.size();if (list.get(m - 1) target) return true;// 分情况遍历所有可能地选择boolean flag;for (int i 0; i m; i) {int curNum cacheNum | (1 list.get(i));if (cached.containsKey(curNum)) flag cached.get(curNum);else {int tempNum list.get(i);int tempTar target - tempNum;list.remove(i);flag dfs(tempTar, !AorB, curNum);cached.put(curNum, flag);list.add(i, tempNum);}if (!flag) return true;}return false;}static boolean isAlwaysWin(int N, int Target) {for (int i 0; i N; i) {int cacheNum 0 | (1 i 1);int tempNum list.get(i);int tempTar Target - tempNum;list.remove(i);if (!dfs(tempTar, B, cacheNum)) return true;list.add(i, tempNum);cached.put(cacheNum, false);}return false;}
//public static void main(String[] args) {// 处理输入输出
// Scanner in new Scanner(System.in);
// String nInput in.nextLine();
// String targetInput in.nextLine();
// int n Integer.parseInt(nInput.replaceAll([^0-9]],));
// int target Integer.parseInt(targetInput.replaceAll([^0-9]],));int n 5;int target 8;// 生成对应的可报数的列表list new ArrayList();cached new HashMap();for (int i 1; i n; i) list.add(i);// 这两种是一个特殊情况刚好是需要顺次报完所有的数字的偶数的话后手必胜奇数的话A必胜if (n % 2 0 target (n 1) * n / 2) System.out.println(false);else if (n % 2 1 target (n 1) * n / 2) System.out.println(true);else// 正常需要迭代判断的情况System.out.println(isAlwaysWin(n, target));//
// System.out.println(isAlwaysWinSingle(list,n,target));}
}总结
过不过再说哈现在先写在这里第一面还行直接让我过了说过两天给我发一道算法题然后让我好好做一下继续在准备晚上去运动一下然后接着看项目加油 8/11今天晚上完成了wind数据的笔试差不多花了四五个小时然后想清楚了也写完了。感觉还行还能继续面试