🚀【不畏挑战,勇往直前】生活从不缺少挑战,正是这些挑战塑造了更加坚韧的你。勇敢地迈出那一步,即使前路未知,也要相信自己的潜力无限。
1、接口和抽象类的区别
接口是一种特殊的抽象类,只能定义抽象方法和静态常量,可以有多个实现类,可以继承多个接口,表示一种功能(微观),一种标准和规范(宏观)
抽象类可以定义属性,构造方法,实例方法,抽象方法,可以有多个子类继承但只有一个父类,用于表示一类事物
一个子类只能继承一个父类,但是可以实现多个接口(单继承,多实现)
2、Java创建对象的方式
1、用new语句创建对象;
2、运用反射手段,调用 java.lang.Class 或者 java.lang.reflect.Constructor 类的 newInstance() 实例方法;
3、调用对象的 clone() 方法;
4、运用反序列化手段,调用 java.io.ObjectInputStream 对象的 readObject() 方法。
3、阻塞队列的特点
队列是一个集合,先进先出。
如果队列为空,执行出队列,会发生阻塞,直到有其他线程执行入队列的操作。如果队列满了,执行入队列的线程会发生阻塞等待,直到有其他线程执行出队列的操作。
阻塞队列的插入(入队)和获取(出队)操作是阻塞的。
阻塞队列通常是线程安全的,多个线程可以并发地执行插入和获取操作,而不会导致数据竞争或不一致的情况。
阻塞队列可以是有界或无界的。
阻塞队列使用等待和通知机制来控制插入和获取操作的阻塞和唤醒。
4、线程安全的集合有哪些,底层设计有哪些特点
Vector,Hashtable
CopyOnWriteArrayList
写有锁,读没有锁,写入时,先copy一个容器副本、再添加新元素,最后替换引用
CopyOnWriteArraySet
底层是CopyOnWriteArrayList,在添加的时候,进行判断值是否存在,如果不存在就添加,存在就不添加
ConcurrentHashMap
写写互斥,读读互斥,ConcurrentHashMap分段加锁,给数组中每一个位置分别加锁,能极大的提高读写的效率
5、HashSet 和 TreeSet 的区别
都是Set的子接口,单例集合,数据不可重复, hashset无序 Treeset有序;
Hashset底层使用的是HashMap哈希表结构储存,而Treeset底层用的是TreeMap树结构储存。
Hashset是通过复写hashCode()方法和equals()方法来保证的,而Treeset是通过Compareable接口的compareTo方法来保证的。
6、Runnable 接口和 Callable 接口的区别
两者最大的不同点是:实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;
Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;
7、乐观锁、悲观锁
乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。使用一定的算法达到线程安全的效果,因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。
乐观锁的实现方式主要有两种:CAS机制(比较交换算法)和版本号机制,
使用的类:ConcurrentLinkedQueue
悲观锁:悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。
悲观锁的实现方式是加锁,加锁既可以是对代码块加锁(如Java的synchronized关键字),或者使用Lock加锁,也可以是对数据加锁(如MySQL中的排它锁)。
使用的类:StringBuffer,Vector,Hashtable
8、HashMap 的底层实现原理
HashMap底层是 数组+链表
实现原理:
首先会创建一个Node对象,把key赋值Node对象的key属性,把value赋值给value属性, 把key值的hash值赋值Node对象的hash属性;
其次需要把这个Node对象放到Node数组中,根据hash值计算,该Node对象存放的位置,如果这个位置没有存放对象,那么就直接把对象放在这个位置,如果这个位置存放对象,就和这个位置的所有对象进行equals的比较,如果没有一个相同的,则追加在最后面,如果有相同的,则把当前Node对象value值覆盖掉相同的Node对象;
随着值的增加,16个位置的数组,已经有12(16*0.75)个已经放值,就是达到加载因子(0.75)定义的范围,数组就会扩容,扩容原来的两倍;
如果数组中元素达到64,且一个位置的上链表中节点的个数达到8,则链表就转化为红黑树,如果该位置的节点删除了,当删除到只剩6个时,就会重新回到链表的数据结构。