前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面经-北京小厂

面经-北京小厂

原创
作者头像
Joseph_青椒
发布2023-08-04 15:08:04
1680
发布2023-08-04 15:08:04
举报
文章被收录于专栏:java_josephjava_joseph

这篇文章记录我的面经—北京小厂

介绍下你吧

代码语言:javascript
复制
从大一下学期开始学java,自己从网上找项目做,一周深挖一个方面的知识,广度方面-分布式这些都有了解
深度方面都有一些基础吧,就是这些。

是不是简历上的在线教育平台啊?是你一个人做的还是

代码语言:javascript
复制
这是一个学长的公司带我一块儿做的  然后没工资,我只是帮忙(笑着说嘿嘿)去学习

在里面都做了什么

代码语言:javascript
复制
比如下单,用rabbit搭建延迟消息这些搭建和设计,他们带我一起学习,有些东西是我去实现的,
一起完善这些落地的东西。

你在项目中解决哪些有代表性的问题?

代码语言:javascript
复制
您是说是比较难的还是些小bug

都可以,你感觉有代表性的,咱们可以聊一聊,

就是下单的时候,不是要往task表插入记录嘛,然后需要通过token去实现放重提交对吧
然后他是通过分布式锁来完成存在删除,保证它多线程下的原子性,但是他这样放重提交,
不能保证有些恶意用户,恶意竞争的商家通过轮询的方式,点一次获取,获取一次,虽然
库存会过一段时间,比如半个小时会释放,但是他这样恶意刷的话,比如100个库存,1个人全部刷完
这种问题,对吧,这里解决当时也是想了好久(笑的很大声) 
有两种策略,一个是限流策略,比如一个用户一分钟只能下一次单这种
第二个就是redis预扣减,当然这里的话,因为是之前的项目,现在才想到这样解决
就是redis预扣减,先在redis预扣减,等支付再进行扣减,就不会有恶意扣库存的问题了
这是我感觉最近学习最深入的

预扣减和实际去扣减去扣减,怎么去同步?

代码语言:javascript
复制
这里我还没深入,是我学习的另一个项目,还没落地到这里,就是知道预扣减的好处

=========================================================
这里一直拖  被八股托太久了 马上就去复盘明白这个redis预扣减

平时在java中,数组和链表如何取舍的?

代码语言:javascript
复制
增加和删除用链表,改查用数组
因为链表是一个连一个的所以用链表,增加和删除会快一点
为啥修改和查看用数组
因为如果要删除一个数组的话,比如我要把那个2删掉,我要把后面的元素整体的移动一下
然后改查的话,数组遍历每一个下标 ,他是O(1级别的,而链表的话需要一个一个遍历
=============================================================
这里我又了解到,甚至是linkedList的作者都不会去使用链表,
因为即使他增加删除快一点,但是他增加删除需要先找到吧,这是对比数组的常数操作,O(1)是很浪费时间的

有没有办法,提高链表的查询速度?

代码语言:javascript
复制
双向链表吧,这样可能会快一点
  
 面试官:那也是,你双向,一个从头一个从尾部,实际没改变
 
 
 这里没了解过
 
 ============================================================================
 这里真的傻了  好气  不过吃一堑长一智  下次知道就行了
 有一个我学过 就是给链表加索引 也就是redis中用的跳表 用二分的思想,但是前提要保证链表有序
 
 LRU问题,在链表的基础上加一个hashmap
 这里推荐这篇文章

[]: https://blog.csdn.net/qq_46489085/article/details/124933345

我们如何比较字符串是否相等呢?

代码语言:javascript
复制
用equals

为什么不用其他的
等于比较的是地址,equlas比较的是堆里的内容

我们平时也会用到,加入程序里要实现乐观锁,你会怎么做?

代码语言:javascript
复制
乐观锁,用一个标识a,另一个我们并发访问的时候可以和他比较,一个线程不符合的话会直接失败
然后就是通过version解决乐观锁的ABA问题,
乐观锁我没在java里实现过,是在超发那里用的乐观锁
直接用的库存大于0这种,这样的乐观锁,这样的粒度比加版本号的小一点
乐观锁的本质,通过自旋和比较,怎么说,通过 emm,默认是没有竞争,假设没竞争这样去做 


面试官:在数据库里面加乐观锁吗?
在sql,扣减嘛  update  stock = stock-1  然后stock>0

===============================================================================
乐观锁在java中常用的cas(compare and swap)顾名思义先比较再替换,
(这里我列几个概念,大家自习了解,也是我之前混淆的,JUC\CAS\AQS,CAS是AQS的基础,AQS是JUC的基础,
所以可以说CAS也是JUC的基础,CAS是非阻塞的算法,synchronized是阻塞的算法,需要注意的是juc可以实现乐观锁和悲观锁)
我们可以利用juc提供的原子类去在程序中实现乐观锁,(Atomicxx类和其中的方法如compareAndSet都是基于CAS算法实现的
(juc包括原子类、工具类和一些接口)Lock接口和他的实现类可以
实现悲观锁(ReentranLock
还有一点需要说明:CAS主要干两件事:锁自旋和乐观锁
所以可以这样回答:java中,可以使用juc提供的原子类和方法实现cas算法,从而实现乐观锁
(也可以把AtomicLong换成普通的Long,但是就必须手动实现一个cas自增的算法了)
如下面例子:
public class User {
    private Long id;
    private String name;
    private Integer age;
    private AtomicLong version;

    // getter 和 setter 方法省略

    // 更新 User 数据
    public void update(User newData) {
        // 读取数据库中的原始数据
        User oldData = userDao.getById(newData.getId());
        // 判断版本号是否相等
        if (oldData.getVersion().get() != newData.getVersion().get()) {
            throw new OptimisticLockException("数据被其他线程修改");
        }
        // 更新数据并增加版本号
        newData.getVersion().incrementAndGet();
        userDao.update(newData);
    }
}

这里再拓展一下:
用时间戳实现乐观锁并不需要原子类,因为时间戳一般都是通过对当前时间的获取来实现的,而对
    时间的获取是线程安全的。

以 User 示例为例,如果我们使用时间戳来实现乐观锁,可以将版本号 version 改为 timestamp
时间戳(毫秒数),然后在每次更新数据时,先从数据库读取旧数据,判断旧数据的 timestamp 是否
等于当前 timestamp,若等于则进行更新操作,否则抛出乐观锁异常。这种实现方式不需要手动实现 
CAS 算法,也不需要使用原子类,代码比较简单:
public class User {
    private Long id;
    private String name;
    private Integer age;
    private long timestamp;

    // getter 和 setter 方法省略

    // 更新 User 数据
    public void update(User newData) {
        // 读取数据库中的原始数据
        User oldData = userDao.getById(newData.getId());
        // 判断时间戳是否相等
        if (oldData.getTimestamp() != newData.getTimestamp()) {
            throw new OptimisticLockException("数据被其他线程修改");
        }
        // 更新时间戳并保存到数据库
        newData.setTimestamp(System.currentTimeMillis());
        userDao.update(newData);
    }
}

总结:
    面试如果可以这样说,一种是通过版本号比较,利用juc提供的原子类和方法,实现cas算法,从而实现乐观锁,
    还有一种就是基于时间戳,时间戳的获取没用并发安全问题,可以不借助原子类,

想深入学习乐观锁的伙伴可以看这篇文章

[]: http://www.manongjc.com/detail/61-jnkzpokxmwhpxul.html

那你对0拷贝做过了解吗

代码语言:javascript
复制
这里看过,但是每记录嘿嘿,当时先把深拷贝和浅拷贝学习了下,然后直接去忘记深入这个了嘿嘿
=====================================================
这里是操作系统方面的知识,
通过各种方式,在特殊情况下,减少数据的拷贝次数或者说减少cpu参与数据拷贝的次数。

我们用多线程,生产者消费者这种场景的话,平时怎么去做的

代码语言:javascript
复制
生产中,我知道的是线程池,不可以去Executors工具类去做,
生产中要自定义,用ThreadPoolExector
这里的阻塞队列要区分C端和B端,如果C端高并发请求下,
他的阻塞队列不可以太长,会有消息的堆积
B端的话要求,不要那么强的实时性,可以让阻塞的队列长一点
然后核心线程数要分io密集型还是cpu密集型,cpu密集型的话可以和cpu核数一致或者加1
io密集型,对cpu没那么高的要求,可以2N+1
然后ThreadPoolExector实现的话主要是核心线程数,最大线程数,拒绝策略,阻塞队列长度
当然拒绝策略使用默认的那个就行
然后这就是我知道的生产消费模型

用这个到项目上面,堆内存怎么配?

代码语言:javascript
复制
您能说的 精确点吗
就是线程池,我们使用的时候,会设计jvm的配置,这里的话会怎么去考虑?
这里的话,线程池的底层是一个hashSet,emmm,这里不会

面试官:比如,线程栈,默认的线程栈的大小,
没去了解过这里...
====================
这里我觉得面试官问的有点问题,jvm调优,应该告诉我一个确定的场景什么的

tcp连接熟吗

代码语言:javascript
复制
这个,他这个计算机网络,这里太多了 学习了 但是想不起来嘿嘿
太多了呜
面试:他有几次挥手啊

三次握手四次回收这样

面试官,假如说,挥手 的时候,有个状态叫closewait,这是什么原因产生的
emm忘记了呜

你是springboot熟还是alibabacloud熟吗

代码语言:javascript
复制
boot吧
面试官:拦截器这里怎么做,平时用过没?
拦截器,Intercepor,比如我用jwt实现登录的时候,就需要拦截请求,做出处理
这就是拦截器,我在这儿用的,

面试官:拦截器加载的顺序?
这里没了解
面试官:就是扩展一个接口,扩展一个类
(这里真蒙了,可能是有人进来了
我蒙了个,::就是实现一个类,重写Interpcptor方法,(这里我真是蒙的嘿嘿  
我补了一句,主要是思想吗,api啥的记不住,用的时候看一下就可以了
===========================================================================
这里说的扩展一个类,就应该是我项目里的LoginInterceptor咋写的
我回顾了下,就是实现HandlerInterceptor接口,重写preHandle和postHandle,和afterCompletion方法
这是添加一个拦截器,
然后每个微服务要注册拦截器,这里需要实现WebMvcConfigurer
重写addInterceptors()方法,registry.addInterceptor去添加自己定义滴拦截器。

然后拦截器的加载顺序:
(下面的就是列举一下,我感觉没必要背会。。)
在 Spring Boot 中,拦截器是通过实现 HandlerInterceptor 接口来定义的。当请求过来时,Spring Boot 会使用一个拦截器链来依次对请求进行拦截和处理,拦截器的加载顺序是与它们在代码中注册的顺序相关的。

具体来说,在 Spring Boot 中,可以通过实现 WebMvcConfigurer 接口,并重写 addInterceptors 方法来注册拦截器。在该方法中,可以使用 addInterceptor 方法来注册拦截器,并使用 order 方法来指定拦截器的优先级。order 数值越小,优先级越高,即越先被调用。

默认情况下,Spring Boot 实现的拦截器链中包含以下几个拦截器(按照执行顺序排序):

ResourceUrlProviderExposingInterceptor
LocaleChangeInterceptor
ThemeChangeInterceptor
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
如果我们在代码中什么都不做,那么这些默认的拦截器就会按照上述顺序被依次执行。如果我们需要自己定义拦截器,可以通过实现 HandlerInterceptor 接口,并在 WebMvcConfigurer 中的 addInterceptors 方法中添加我们自己的拦截器并指定其 order 值,从而改变拦截器执行的顺序。

面向对象里面有重载,对一个方法重载怎么实现

代码语言:javascript
复制
就是把形式参数改一下就是重载

大概情况我们就了解这么多,对我们公司有想知道的吗

代码语言:javascript
复制
公司的规模大概多大
面试官:我们公司有差不多400号人
我:属于小中厂是吗
面试官:小厂是吗

你在哪个地方

代码语言:javascript
复制
吉林
面试官:我们的公司在北京,有什么影响吗
我:大三也没啥课
准备暑期之后,上课的话也可以找人代课吗,实习挺重要的
面试官:所以可以在北京一直呆着是吗
对

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这篇文章记录我的面经—北京小厂
    • 介绍下你吧
      • 是不是简历上的在线教育平台啊?是你一个人做的还是
        • 在里面都做了什么
          • 你在项目中解决哪些有代表性的问题?
            • 预扣减和实际去扣减去扣减,怎么去同步?
              • 平时在java中,数组和链表如何取舍的?
                • 有没有办法,提高链表的查询速度?
                  • 我们如何比较字符串是否相等呢?
                    • 我们平时也会用到,加入程序里要实现乐观锁,你会怎么做?
                      • 那你对0拷贝做过了解吗
                        • 我们用多线程,生产者消费者这种场景的话,平时怎么去做的
                          • 用这个到项目上面,堆内存怎么配?
                            • tcp连接熟吗
                              • 你是springboot熟还是alibabacloud熟吗
                                • 面向对象里面有重载,对一个方法重载怎么实现
                                  • 大概情况我们就了解这么多,对我们公司有想知道的吗
                                    • 你在哪个地方
                                    领券
                                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档