int和Integer的区别

    作为成员变量来说,Integer的初始值为null,int初始值为0
    Integer是对象,存储在堆内存;int类型直接存储在栈空间
    Integer封装了很多方法和属性,使用时更加灵活

为什么设计封装类型?

因为java本身是个面向对象的语言,一切操作都是以对象作为基础,比如集合(ArrayList,HashMap)里存的元素,也只支持存储Object类型,普通类型无法通过集合存储
JDK、JRE、JVM的区别

JDK是java标准开发包,提供编译、运行java程序所需的各种工具和资源,包括java编译器、java运行时环境,以及常用的java类库

JRE是java运行环境,用于运行java的字节码文件,JRE包括JVM和JVM工作时所需的类库,普通用户只需要安装JRE来运行java程序,而程序开发者必须安装JDK来编译调试程序

JVM是java虚拟机,是JRE的一部分,整个java实现跨平台的最核心部分,负责运行字节码文件

    详细解释如下图:

    在这里插入图片描述

==和equals方法的区别

==:如果是基本数据类型,比较的是值;引用类型比较的是引用地址
equals:具体看各个类重写equals方法后的比较逻辑,比如String类,虽然是引用类型。但是String类中重写了equals方法,内部比较的是各个字符是否全部相等
hashCode()与equals()之间的关系

首先hashCode的判断:

    两个对象的hashCode不同,则肯定是不同的两个对象
    hashCode相同,对象不一定相同
    两个对象相等。hashCode一定相同

    在这里插入图片描述

所以重写 equals 方法的时候需要重写 hashCode 方法,许多容器类,如 HashMap、HashSet 都依赖于 hashcode 与 equals 的规定。
泛型中extends和super的区别

<? extends T> 表示包括T在内的任何T的子类

<? super T> 表示包括T在内的任何T的父类

    1
    2
    3

String、StringBuffer、StringBuilder的区别

    String有final修饰,是不可变的,如果修改,会产生一个新的字符串,StringBuffer和StringBuilder是可变的
    StringBuffer线程安全,StringBuilder线程不安全(不同步)。所以单线程环境下StringBuilder效率更高

重载和重写的区别

重载:发生在同一个类中,方法名相同,参数类型、个数、顺序不同,返回值、访问修饰符不做要求。发生在编译时。
重写:发生在父子类中,方法名、参数列表必须相同,返回值范围小于父类,抛出异常范围小于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private子类就不能重写该方法。

public int add(int a,String b)
public String add(int a,String b)
//编译报错

    1
    2
    3

接口和抽象类的区别

    抽象类可以存在普通成员函数,而接口中只能存在public abstract方法
    抽象类中的成员变量可以是各种类型,接口中成员变量只能是public final类型
    抽象类只能继承一个,接口可以实现多个

扩展:

    接口的设计目的是对类的行为进行约束,只约束行为的有无,不对如何实现进行限制。表达的是like a的关系,如Bird like a Aircraft但本质是is a Bird,核心是定义行为,实现类做法他不关心。

    抽象类设计目的在于代码复用,如果不同的类具有相同的行为,我们就把共性的东西抽象出来,派生出抽象类。为is a的关系,如BWM is a Car。即先有子类再有父类,把子类共性抽取为父类。有些方法实现了,有些没实现,调的话不知道执行谁,所以抽象类不允许实例化出来

    关心事物本质,用抽象类;关注操作,用接口。

List与Set的区别

    List:有序,按对象进入的顺序保存对象,可重复,孕妇多个Null元素对象,可以使用Iterator取出所有元素,再逐一遍历,还可以使用get(int index)获取指定下标的元素
    Set:无序,不可重复,最多允许有一个Null元素对象,取元素时只能用Iterator接口取得所有元素,再逐一遍历各个元素

ArrayList和LinkedList的区别

    底层数据结构不同,ArrayList底层是基于数组实现的,LinkedList底层是基于链表实现的
    适应场景不同,ArrayList更适合随机查找,LinkedList更适合删除和添加
    都实现了List接口,但是LinkedList还额外实现了Deque接口,所以LinkedList还可以当作队列来使用

    ArrayList在这里插入图片描述

    LinkedList在这里插入图片描述

⭐HashMap与HashTable的区别?底层实现是什么?

    HashMap没有synchronized修饰,不安全。HashTable线程安全;

    HashMap允许key和value为null,HashTable不允许
    在这里插入图片描述

⭐ConcurrentHashMap原理,jdk7和jdk8的区别

在这里插入图片描述
java中的异常体系

在这里插入图片描述
解释:

Java中的所有异常都来自顶级父类Throwable。
Throwable下有两个子类Exception和Error。
Error是程序无法处理的错误,一旦出现这个错误,则程序将被迫停止运行。
Exception不会导致程序停止,又分为两个部分RunTimeException运行时异常和CheckedException检查异常。
RunTimeException常常发生在程序运行过程中,会导致程序当前线程执行失败。
CheckedException常常发生在程序编译过程中,会导致程序编译不通过。

    1
    2
    3
    4
    5
    6

⭐CopyOnWriteArrayList的底层原理

    首先CopyOnWriteArraryList内部也是数组实现,再向CopyOnWriteArrayList添加元素时,会复制一个新的数组,写操作再新数组上进行,读操作在原数组上进行
    写操作会加锁,防止出现并发写入丢失数据的问题
    写操作结束后会把原数组指向新数组
    CopyOnWriteArrayList允许在写操作时来读取数据,提高了读性能,因此适合读多写少的应用场景,但是CopyOnWriteArrayList比较占内存,同时数据不是实时最新的数据,所以不适合实时性要求高的场景

⭐Final的理解

最终的

    修饰类:不可被继承
    修饰方法:不可被子类覆盖,但可以重载
    修饰变量:表示变量一旦被赋值就不可被更改

    进阶扩展:在这里插入图片描述
    在这里插入图片描述
    **

线程的生命周期,线程有哪些状态

五种状态:创建、就绪、运行、阻塞、死亡

    图片来源:https://www.pdai.tech/md/interview/x-interview.htmlhttps://www.pdai.tech/md/interview/x-interview.html#_3-1-%E5%B9%B6%E5%8F%91%E5%9F%BA%E7%A1%80

    在这里插入图片描述

    五状态描述在这里插入图片描述

锁池与等待池

    锁池
    所有需要竞争同步锁的线程都会放在锁池当中,比如当前对象的锁已经被其中一个线程得到,则其他线程需要在这个锁池进行等待,当前面的线程释放同步锁后锁池中的线程去竞争同步锁,当某个线程得到后会进入就绪队列进行等待cpu资源分配。
    等待池
    当我们调用wait()方法后,线程会放到等待池当中,等待池的线程是不会去竞争同步锁。只有调用了notify()或notifyAll()后等待池的线程才会开始去竞争锁,notify()是随机从等待池选出一个线程放到锁池,而notifyAll()是将等待池的所有线程放到锁池当中

⭐Sleep()、wait()、join()、yield()的区别

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

对线程安全的理解

    堆在这里插入图片描述

    栈在这里插入图片描述

堆在虚拟机启动时创建,栈在线程开始时初始化
Thread和Runnable的区别

    Thread和Runnable的实质是继承关系,没有可比性。无论使用Runnable还是Thread,都会new Thread,,然后执行run方法。
    用法上,如果有复杂的线程操作需求,那就选择继承Thread,如果只是简单的执行一个任务,那就实现runnable。

    网上常见的问题:下面两代码中Runnable和Thread运行结果为什么不同?
    在这里插入图片描述在这里插入图片描述

上述问题在于上面Thread new了俩对象,而Runnable new了一个对象,结果Runnable正常售出票。不能说明Runnable比Thread更安全!
⭐对守护线程的理解

    守护线程不是某一个用户线程的,而是所有用户线程的守护线程。
    守护线程依赖整个进程而运行,当没有线程要执行即进程结束了,守护线程就自动中断了。
    守护线程的终止是自身无法控制的,不要把IO、File等重要的操作逻辑分配给它。

    在这里插入图片描述

    thread.setDaemon(true)必须在thread.start()之前设置,否则会抛出一个IllegalThreadStateException异常。你不能把正在运行的常规线程设置为守护线程。
    在Daemon线程中产生的新线程也是Daemon的。
    守护线程不能用于去访问固有资源,比如读写操作或者计算逻辑。因为它会在任何时候甚至在一个操作的中间发生中断。
    Java自带的多线程框架,比如Executorservice,会将守护线程转换为用户线程,所以如果要使用后台线程就不能用ava的线程池。

⭐ThreadLocal的原理和使用场景

在这里插入图片描述

    每一个Thread对象均含有一个ThreadLocalMap类型的成员变量threadLocals它存储本线程中所有ThreadLocal对象及其对应的值
    ThreadLocalMap由一个个Entry对象构成
    Entry继承自weakReference<ThreadLocal<?>>一个Entry由ThreadLocal对象和object构成。由此可见,Entry的key是ThreadLocal对象,并且是一个弱引用。当没指向key的强引用后,该key就会被垃圾收集器回收
    当执行set方法时,ThreadLocal首先会获取当前线程对象,然后获取当前线程的ThreadLocalMap对象。再以当前ThreadLocal对象为key,将值存储进ThreadLocalMap对象中。
    get方法执行过程类似。ThreadLocal首先会获取当前线程对象,然后获取当前线程的ThreadLocalMap对象。再以当前ThreadLocal对象为key,获取对应的value。
    由于每一条线程均含有各自私有的ThreadLocalMap容器,这些容器相互独立互不影响,因此不会存在线程安全性问题,从而也无需使用同步机制来保证多条线程访问容器的互斥性。

使用场景:

    在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束。
    线程间数据隔离
    进行事务操作,用于存储线程事务信息。
    数据库连接,Session会话管理。

    Spring框架在事务开始时会给当前线程绑定一个Jdbc connection,在整个事务过程都是使用该线程绑定的connection来执行数据库操作,实现了事务的隔离性。Spring框架里面就是用的ThreadLocal来实现这种隔离。

⭐⭐ThreadLocal内存泄漏原因,如何避免

    内存泄漏是什么?
    不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

并发、并行、串行

    并行在时间上是重叠的,两个任务在同一时刻互不干扰的同时执行。
    并发允许两个任务彼此干扰。统一时间点、只有一个任务运行,交替执行
    串行在时间上不可能发生重叠,前一个任务没搞定,下一个任务就只能等着

⭐并发三大特性

原子性、有序性、可见性

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

⭐为什么用线程池,解释下线程池参数

    降低资源消耗:提高线程利用率,降低创建和销毁线程的消耗。
    提高响应速度:任务来了,直接有线程可用可执行,而不是先创建线程,再执行。
    提高线程的可管理性:线程是稀缺资源,使用线程池可以统一分配调优监控。

    在这里插入图片描述

⭐简述线程池的处理流程

在这里插入图片描述
在这里插入图片描述
⭐线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最大线程

阻塞队列:

    保存任务在阻塞队列中
    在没有任务要执行的情况下,自动阻塞获取任务的线程(比如核心线程),释放cpu资源

    在这里插入图片描述

⭐线程池中线程复用原理

业务逻辑并没有写在线程池中线程的run方法里,而是利用线程调用任务里面的run方法