JAVA大厂面试题部分整理

序列化的底层怎么实现

序列化是指将Java对象转换为字节序列的过程,而反序列化是指将字节序列转换为Java对象的过程。其中,字节序列即是二进制数据,可以方便地在网络上传输或存储到本地硬盘中。

1、JDK类库中序列化和反序列化API

(1)java.io.ObjectOutputStream:表示对象输出流;

它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中;

(2)java.io.ObjectInputStream:表示对象输入流;

它的readObject()方法源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回;

2、实现序列化的要求

只有实现了Serializable或Externalizable接口的类的对象才能被序列化,否则抛出异常!

3、实现Java对象序列化与反序列化的方法

假定一个User类,它的对象需要序列化,可以有如下三种方法:

(1)若User类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化

ObjectOutputStream采用默认的序列化方式,对User对象的非transient的实例变量进行序列化。 
ObjcetInputStream采用默认的反序列化方式,对对User对象的非transient的实例变量进行反序列化。

(2)若User类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。

ObjectOutputStream调用User对象的writeObject(ObjectOutputStream out)的方法进行序列化。 
ObjectInputStream会调用User对象的readObject(ObjectInputStream in)的方法进行反序列化。

(3)若User类实现了Externalnalizable接口,且User类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。

ObjectOutputStream调用User对象的writeExternal(ObjectOutput out))的方法进行序列化。 
ObjectInputStream会调用User对象的readExternal(ObjectInput in)的方法进行反序列化

 synchronized的底层怎么实现

Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象

https://www.cnblogs.com/paddix/p/5367116.html

tomcat集群怎么保证同步

https://blog.csdn.net/weixin_43258908/article/details/89199735

怎么解决项目中的超卖问题

由秒杀引发的一个问题

  • 秒杀最大的一个问题就是解决超卖的问题。其中一种解决超卖如下方式:
update goods set num = num - 1 WHERE id = 1001 and num > 0

我们假设现在商品只剩下一件了,此时数据库中 num = 1;

但有100个线程同时读取到了这个 num = 1,所以100个线程都开始减库存了。

但你会最终会发觉,其实只有一个线程减库存成功,其他99个线程全部失败。

为何?

这就是MySQL中的排他锁起了作用。

排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

就是类似于我在执行update操作的时候,这一行是一个事务(默认加了排他锁)。这一行不能被任何其他线程修改和读写

 

  • 第二种解决超卖的方式如下
 
select version from goods WHERE id= 1001
update goods set num = num - 1, version = version + 1 WHERE id= 1001 AND num > 0 AND version = @version(上面查到的version);

这种方式采用了版本号的方式,其实也就是CAS的原理。

假设此时version = 100, num = 1; 100个线程进入到了这里,同时他们select出来版本号都是version = 100。

然后直接update的时候,只有其中一个先update了,同时更新了版本号。

那么其他99个在更新的时候,会发觉version并不等于上次select的version,就说明version被其他线程修改过了。那么我就放弃这次update

  • 第三种解决超卖的方式如下

 利用redis的单线程预减库存。比如商品有100件。那么我在redis存储一个k,v。例如 <gs1001, 100>

每一个用户线程进来,key值就减1,等减到0的时候,全部拒绝剩下的请求。

那么也就是只有100个线程会进入到后续操作。所以一定不会出现超卖的现象

  • 总结

可见第二种CAS是失败重试,并无加锁。应该比第一种加锁效率要高很多。类似于Java中的Synchronize和CAS

 int的范围

-2^31——2^31-1

说说快速排序,实现过程,复杂度

https://www.cnblogs.com/yangecnu/p/Introduce-Quick-Sort.html

时间复杂度这个东西真的看不懂

 乐观锁vs悲观锁

https://blog.csdn.net/m0_37316406/article/details/105187049

GC

https://blog.csdn.net/weixin_36027342/article/details/79973294?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task 

 设计模式怎么分类,每一类有哪些

https://www.cnblogs.com/call-me-pengye/p/12201675.html

 并发包里了解哪些

 https://blog.csdn.net/varyall/article/details/80288084

 b树,b+树,b*

https://blog.csdn.net/m0_37316406/article/details/105248460

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值