JAVA

面试复习之Java知识解答

2019-07-30  本文已影响0人  街道shu记

Java知识复习解答

1.synchronize 和 volitale的区别;什么是可见性和原子性

可见性:当一个线程修改了线程共享变量的值,其他线程能够立即得知这个修改

原子性:一系列的操作要么全部执行完,要么都不执行

有序性:如果在本线程内观察,所有操作都是有序的;如果在一个线程中观察另一个线程,所有操作都是无序的。前半句是指“线程内表现为串行语义”,后半句是指“指令重排序”现象和“工作内存中主内存同步延迟”现象。

synchronized具有原子性,可见性,有序性,同一时刻只能有一个线程进行获取;会造成线程阻塞;标记的变量会被编译器优化;可以使用在变量,方法,类级别中

volatile具有可见性,有序性,不能保证原子性,(需要保证原子性,1:运算结果不依赖变量的当前值,或者只有一个线程修改变量的值;2:该变量没有包含在具有其他变量的不变式中);不会造成线程阻塞;标记的变量不会被编译器优化(防止指令重排);只能使用在变量级别

2.Java的集合类

Java的集合类是放在java.util包下;集合类存放的是对象的引用,而非对象的本身;集合类主要分为Set(集),List(列表),Map(映射)。

List和Set是Collection(接口)的子类。

Set:不能包含重复的元素,没有顺序

List:

  1. ArrayList:是List的子类,底层是动态扩容的数组结构。可以存放重复的元素(包括null);有序,按照元素的添加顺序,多用于查询多增删操作少的情况,ArrayList是线程异步的,是不安全。

    扩容机制:每次扩容的大小是原来的1.5倍;扩容的过程其实就是一个将原来元素拷贝到一个扩容后数组大小的长度新数组中,所以ArrayList的扩容其实是相对来说是比较消耗性能的。经常出现的一个异常:ConcurrentModificationException,在foreach循环的时候,进行了删除操作,集合的长度产生的变化,

  2. LinkedList:LinkedList是一种可以在任何位置进行高效地插入和删除操作的有序序列,多用于增删操作多的情况下。底层实现的数据结构是双向链表。也是不安全的

Map是util包下另一个集合类,是以key-value形式,键不能重复,值可以重复。对Map集合遍历时先得到键的set集合,再对set集合进行遍历,得到相应的值。

HashMap:

  1. 存储数据是根据键值对存储数据的,并且存储多个数据时,数据的键不能相同,如果相同该键之前对应的值将被覆盖。
  2. HashMap最多只允许一条存储数据的键为null,可允许多条数据的值为null。
  3. HashMap存储数据的顺序是不确定的,并且可能会因为扩容导致元素存储位置改变。因此遍历顺序是不确定的。
  4. HashMap是线程不安全的,使用ConcurrentHashMap具有线程安全。

底层存储结构:

JDK1.7之前的存储结构:

拉链法,专业点就叫链地址法。就是数组加链表的结合。每一个数组元素上存储的都是一个链表。新添加进来的元素总是放在数组对应的角标位置,而原来处于该角标的位置的节点作为next节点放到新节点的后边。

JDK1.8中的数据结构:

如果单单是数组加链表的话,当处理hash值冲突较多的情况下,链表的长度会越来越长,查找的效率会越来越低了。所以在1.8中当新增节点导致链表的长度超过8的时候,就会在添加元素的同事将单链表转化为红黑树。红黑树是一种易于增删改查的二叉树,这样HashMap中的元素操作起来就会更高效。

3. Java中的引用

4. Java GC回收机制

GC机制:是Java虚拟机垃圾回收器提供的一种用于在空闲时间不定时回收无任何对象引用的对象占据的内存空间的一种机制。

JVM把内存划分成了下面几个区域:

方法区和堆归所有线程共享

在上面介绍的五个内存区域中,有3个是不需要进行垃圾回收的:本地方法栈、程序计数器、虚拟机栈。因为他们的生命周期是和线程同步的,随着线程的销毁,他们占用的内存会自动释放。所以,只有方法区和堆区需要进行垃圾回收,回收的对象就是那些不存在任何引用的对象。

GC算法:

经典的引用计数算法,很难处理循环引用关系,所以Java并没有采用这种方法。而是采用追踪性垃圾收集,就是根搜索算法。

常见的垃圾收集算法:

5.Java的内存模型

Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。

6.多进程和多线程

进程是资源分配的最小单位,线程是CPU调度的最小单位

7. 线程的休眠方式,sleep和wait哪个会释放锁?

sleep是Thread类的方法,不会释放对象锁。

wait是Objec类的方法,线程会释放对象锁,可以用notify()或者notifyAll()唤醒。

8. String、StringBuffer、StringBuilder的区别

都是被final修饰的,都不允许被继承。

String长度固定,StringBuffer和StringBuilder长度是可以改变的;StringBuffer是线程安全的,StringBuilder不是线程安全的。StringBuffer多用于多线程,操作大量数据,StringBuilder用于单线程操作大量数据,效率优于StringBuffer;拼接字符串不建议使用+,因为内部也是额外创建StringBuffer来完成的。

9. 抽象类和接口有什么区别?

共同点:是上层的抽象层。 都不能被实例化。 都能包含抽象的方法,这些抽象的方法用于描述类具备的功能,但是不会提供具体的实现。

区别:抽象类里面可以写非抽象方法,接口中只能有抽象方法;类只能继承一个类,可以是抽象类。类可以实现多个接口。抽象类抽象方法可以用所有修饰符修饰,接口里面的方法都是public,在JDK1.8允许一个静态方法和多个Default方法。抽象类可以有构造方法,接口不能有构造器。

10.单例模式,双判空懒汉单例模式,为什么变量用volitale修饰,new不是原子操作

用volitale修饰,是禁止指令重排。new不是原子操作,有多个步骤。

上一篇下一篇

猜你喜欢

热点阅读