京东Java开发一面
作者:offer快来到碗里
链接:https://www.nowcoder.com/discuss/611079?type=0&order=1&pos=8&page=1&channel=-1&source_id=discuss_center_0_nctrack
来源:牛客网
-
介绍一下怎么防止发生超卖
解释:
背景:如果是MySQL数据库,可以使用它自带的锁机制很好的解决问题,但是,在大规模并发的场景中,是不推荐使用MySQL的。秒杀和抢购的场景中,还有另外一个问题,就是“超发”,如果在这方面控制不慎,会产生发送过多的情况。我们也曾经听说过,某些电商搞抢购活动,买家成功拍下后,商家却不承认订单有效,拒绝发货。这里的问题,也许并不一定是商家奸诈,而是系统技术层面存在超发风险导致的。
解决方式:
1)悲观锁
悲观锁,也就是在修改数据的时候,采用锁定状态,排斥外部请求的修改。遇到加锁的状态,就必须等待。
虽然上述的方案的确解决了线程安全的问题,但是,别忘记,我们的场景是“高并发”。也就是说,会很多这样的修改请求,每个请求都需要等待“锁”,某些线程可能永远都没有机会抢到这个“锁”,这种请求就会死在那里。同时,这种请求会很多,瞬间增大系统的平均响应时间,结果是可用连接数被耗尽,系统陷入异常。2)FIFO的思路
那么我们稍微修改一下上面的场景,我们直接将请求放入队列中的,采用FIFO(First Input First Output,先进先出),这样的话,我们就不会导致某些请求永远获取不到锁。看到这里,是不是有点强行将多线程变成单线程的感觉哈。
然后,我们现在解决了锁的问题,全部请求采用“先进先出”的队列方式来处理。那么新的问题来了,高并发的场景下,因为请求很多,很可能一瞬间将队列内存“撑爆”,然后系统又陷入到了异常状态。或者设计一个极大的内存队列,也是一种方案,但是,系统处理完一个队列内请求的速度根本无法和疯狂涌入队列中的数目相比。也就是说,队列内的请求会越积累越多,最终Web系统平均响应时候还是会大幅下降,系统还是陷入异常。3)乐观锁
这个时候,我们就可以讨论一下“乐观锁”的思路了。乐观锁,是相对于“悲观锁”采用更为宽松的加锁机制,大都是采用带版本号(Version)更新。实现就是,这个数据所有请求都有资格去修改,但会获得一个该数据的版本号,只有版本号符合的才能更新成功,其他的返回抢购失败。这样的话,我们就不需要考虑队列的问题,不过,它会增大CPU的计算开销。但是,综合来说,这是一个比较好的解决方案。
有很多软件和服务都“乐观锁”功能的支持,例如Redis中的watch就是其中之一。通过这个实现,我们保证了数据的安全。 -
实现多线程的方式
解释:
1)继承Thread并重写run方法,并调用start方法
2)实现Runnable接口,并用其初始化Thread,然后创建Thread实例,并调用start方法
3)实现Callable接口,并用其初始化Thread,然后创建Thread实例,并调用start方法
4)使用线程池创建
代码参考:https://blog.youkuaiyun.com/zhaohong_bo/article/details/89224545 -
线程池的7大参数
解释:
-
介绍一下Redis
解释:
-
你知道缓存锁吗
解释:
-
Redis的数据类型,项目中哪里有用到
解释:
-
Redis的缓存雪崩、缓存击穿和缓存穿透
解释:
-
讲一下hashmap
解释:
-
java8之后为什么引入元空间
解释:
-
介绍一下你了解的算法
解释:
-
链表翻转和二分查找
解释:
-
要读取几千万条数据,给你3台4核8G的处理器,让你设计一个多线程去读,核心线程数怎么设计,依据是什么,最大核心线程池大小,线程池是自己写还是用自带的,为什么?拒接策略怎么选择,为什么?
解释: