1,StringBuffer与StringBuilder的区别,及实现原理
1、StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,
2、只是StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因此是线程安全的,
而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。
3、在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全
而StringBuffer则每次都需要判断锁,效率相对更低
实现原理
StringBuffer类继承自AbstractStringBuilder抽象类,实现Serializable序列化接口和CharSequence接口。
编辑网络异常,图片无法展示|AbstractStringBuilder抽象类实现Appendabel,CharSequence接口。
一旦定义之后不可改变,能够改变的String变量的引用地址。比如String b=new String ();指向String 创建的在堆中的对象地址,b= new String("ssss");这样b再次指向另一个在堆中的某一对象地址。而之前堆中的String对象的value是常量并没有发生改变
简而言之创建的String变量可以重新指向对象但是String的一个对象中的value数组是不能改变的这也就是为什么定义的对象无法进行末尾追加值的原因(因为你想要改变String的长度需要操作value对象而value对象呗关键字final修饰了)。
这三个类在进行操作时的速度关系为:StringBuilder > StringBuffer > String
由于String中进行操作时都会新建一个char[ ]数组代替原来的char[ ]数组,所以速度最慢
StringBuffer线程安全,每个方法都有synchronized同步阻塞,所以操作速度受影响
StringBuilder没有同步阻塞的限制,所以操作速度最快
使用场景
- 如果要操作少量的数据用 = String
- 单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
- 多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
2,接口和抽象类的区别
相同点:
- 都无法实例对象
- 可以定义无方法体的方法
不同点:
- 抽象类是一种类只能单继承 接口可以多实现
- 抽象类中 可以有普通方法 接口在jdk1.8之前是不可以定义普通方法的
- 抽象类中可以有普通变量 接口中的变量都是由final修饰的
- 抽象类可以有构造器和主方法(抽象类中的构造器主要是在子类的构造方法中调用 负责初始化抽象类中的参数) 接口中不可以有构造器和主方法
- 抽象类中的方法普通可以由public private protected 和默认修饰 抽象方法可以由 public protected(或者不加修饰符)修饰 抽象方法必须由abstract修饰 接口方法默认由public修饰 接口中的抽象方法只能由public修饰 default在接口中只能修饰带有方法体的方法
使用场景
- 当需要一些默认的方法实现时需要使用抽象类
- 当需要多继承时使用接口
- 当需要不断增加基础功能的时候使用抽象类 当使用接口时 增加功能就需要修改每个实现了该接口的实现类
3 arraylist 和hashMasp 初始容量值是多少,加载因子是多少。扩容是怎么扩的
1.8中,如果只是new ArrayList() ,容量其实是0,当第一次通过add(E e)时,才扩充为10
扩容:
ArrayList扩容的核心方法grow(),下面将针对三种情况对该方法进行解析:
1,当前数组是由默认构造方法生成的空数组并且第一次添加数据。此时minCapacity等于默认的容量(10)那么根据下面逻辑可以看到最后数组的容量会从0扩容成10。而后的数组扩容才是按照当前容量的1.5倍进行扩容;
2,当前数组是由自定义初始容量构造方法创建并且指定初始容量为0。此时minCapacity等于1那么根据下面逻辑可以看到最后数组的容量会从0变成1。这边可以看到一个严重的问题,一旦我们执行了初始容量为0,那么根据下面的算法前四次扩容每次都 +1,在第5次添加数据进行扩容的时候才是按照当前容量的1.5倍进行扩容。
3,当扩容量(newCapacity)大于ArrayList数组定义的最大值后会调用hugeCapacity来进行判断。如果minCapacity已经大于Integer的最大值(溢出为负数)那么抛出OutOfMemoryError(内存溢出)否则的话根据与MAX_ARRAY_SIZE的比较情况确定是返回Integer最大值还是MAX_ARRAY_SIZE。这边也可以看到ArrayList允许的最大容量就是Integer的最大值(-2的31次方~2的31次方减1)。
ArrayList:
- 线程不安全,查询速度快
- 底层数据结构是数组结构
- 扩容增量:原容量的 0.5倍+1
如 ArrayList的容量为10,一次扩容后是容量为16
HashMap,默认大小是16,也就是支持存储最多20个键值对。如果不超过20个键值对,可以不设置,如果超出,按如下公式计算后设置:initialCapacity = (需要存储的元素(键值对)个数 / 负载因子) + 1。
注意负载因子(即loader factor)默认为0.75
HashMap
5 waite sleep 区别
- sleep()方法,属于Thread类中的。而wait()方法,则是属于Object类中的。
- sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
- 在调用sleep()方法的过程中,线程不会释放对象锁。
- 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备
- sleep是Thread线程类的方法,而wait是Object顶级类的方法
- sleep可以在任何地方使用,而wait只能在同步方法或者同步块中使用。
其他问题:
- exception的父类是什么?
- hashmap是线程不安全的,如果要线程安全的用什么?
- 他的线程安全是如何实现的?
- 为什么分段和链表就线程安全了?
- spring aop原理?一般用在什么地方?
- jvm堆服务那几个代?
- 线程池thread pool有哪几个核心参数?
- 高并发情况下,数据库扛不住如何处理?
- 不用mq如何实现秒杀?