这些Java基础知识,诸佬们都还记得嘛(学习,复习,面试都可)

举报
酸菜鱼. 发表于 2022/11/30 21:18:04 2022/11/30
【摘要】 🚗线程之间的通信方式在多线程环境下中,Java提供了两种多线程之间的通信方式。一个是基于monitor对象锁的形式实现通信,另一种是基于condition条件队列实现线程之间的通信方式的。我们在前面谈到过,synchronized关键字是基于monitor对象锁实现的,因此,当我们使用synchronized方法同步时,就会用到monitor对象锁。而对于monitor锁,是调用了Obj...

🚗线程之间的通信方式

在多线程环境下中,Java提供了两种多线程之间的通信方式。一个是基于monitor对象锁的形式实现通信,另一种是基于condition条件队列实现线程之间的通信方式的。我们在前面谈到过,synchronized关键字是基于monitor对象锁实现的,因此,当我们使用synchronized方法同步时,就会用到monitor对象锁。而对于monitor锁,是调用了Object类中的wait,notify,notifyAll等方法来对使线程等待/唤醒的。对于条件队列condition,我们在讲解Lock锁的时候谈到过。当我们使用Lock锁方法同步时,会用到条件队列condition实现线程间的通信,而condition对象是通过Lock锁创建出来的对象,调用其中的await,sign,signAll等方法来实现线程之间的通信的。
在这里插入图片描述

抽象类和接口的区别

首先解释什么是抽象类:
将类与类之间的共同特征提取出来,就可以形成抽象类。
抽象类不能直接实例化对象,但可以使用多态即父类的引用指向子类的对象,抽象类作为父类。
什么是接口:
接口可以看做特殊的抽象类,当然接口也无法实例化和创建对象,在使用时也可以使用多态,父类的引用指向子类的对象,这里的父类就是接口。

区别:

  • 抽象类体现的是继承关系(extends),接口体现的是实现关系(implements),一个类可以实现多个接口,而类只能继承一个抽象类。
  • 抽象类中可以定义,普通方法,静态方法,抽象方法,提供给子类使用,而接口中的方法都是抽象的,接口中的成员都有固定的修饰符。
  • 抽象类中可以有构造方法,而接口中不可以有构造方法
  • 抽象类中的抽象方法的访问类型可以是public,protected,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。

🚓JVM的内存模型

JVM由三部分组成:类加载子系统,执行引擎,运行时数据区。

类加载子系统:可以根据指定的全限定名来载入类或者接口。
执行引擎:负责执行那些被载入类的方法指令。
运行时数据区:运行时数据区分为程序计时器(存储程序运行位置的字节码行号指示器),堆内存(存储所有创建的对象,数组等),虚拟机栈(主要存储方法,局部变量,运行的数据),本地方法栈{主要存储本地方法(含有Native关键字的方法)},方法区(存储虚拟机加载的字节码数据,常量,静态变量,运行时常量池等)。当程序运行的时候,JVM会在内存中存储很多的内容,比如:字节码,对象,参数,局部变量,运算的中间结果等,这些数据都在运行时数据区,方便管理。

🚕JVM的垃圾回收器有哪些

用于新生代的垃圾回收器有Serial,ParNew,Parallel Scavenge;适合老年代的垃圾回收器有Serial Old,Parallel Old ,CMS;G1为整堆垃圾收集器。

Serial and SerialOld

Serial收集器是最基础的垃圾收集器,Serial收集器是只允许单线程工作的垃圾收集器,同一时刻只有一个垃圾收集器线程回收垃圾,在该线程执行时,会暂停其他所有的工作线程,直到垃圾收集器线程收集完垃圾为止。在此过程中,暂停其他工作线程的行为被称为STW(Stop The World)。

Serial Old垃圾收集器是Serial收集器的老年代版本,因为两者相似,所以放到一起介绍。
Serial Old垃圾收集器和Serial收集器一样,都是单线程的收集器,使用的垃圾清除算法是标记整理法。

🛺ParNew

ParNew垃圾收集器是Serial垃圾收集器的多线程并发执行的版本,在使用此垃圾回收器收集垃圾时,会创建多个线程进行垃圾回收,并且也会发生STW(Stop The World)。其他的包括垃圾收集算法,对象分配,回收策略都和Serial垃圾收集器的一致。

在这里插入图片描述

🚙Parallel Scavenge and Parallel Old

Parallel Scavenge垃圾收集器是基于标记复制算法实现的收集器,此收集器也是多线程并行的垃圾收集器,Parallel Scavenge垃圾收集器的目标是达到一个可控制的吞吐量。

Parallel Old垃圾收集器是Parallel Scavenge垃圾收集器的老年代版本,同样,它也支持多线程并行来回收垃圾,使用的垃圾回收算法是标记整理算法。此收集器也是注重吞吐量优先的垃圾收集器。

🚌CMS

CMS收集器的全称为Concurrent Mark Sweep,在中文里有并发标记清除的意思,因此CMS垃圾收集器是基于标记清除算法实现的,CMS垃圾回收器是用于老年代回收垃圾的收集器,它是以获取最短回收停顿时间为目标的垃圾收集器。在CMS垃圾收集器运行的过程中包括四个步骤:初始标记,并发标记,重新标记,并发清除。

🚐G1

G1垃圾收集器的全称为Garbage First,它适合于大内存多核CPU的服务器,它不是按照新生代和老年代去收集垃圾的,它是面向堆内存中的任何部分来回收的,衡量哪块内存中的垃圾最多,回收效率最大。G1垃圾收集器运行的过程中包括四个步骤:初始标记,并发标记,最终标记,筛选回收。其中初始标记和最终标记步骤需要发生STW,停止其他的工作线程。

在这里插入图片描述

🚎Java中的四种引用方式

Java中的四种引用方式有:强引用,软引用,弱引用,虚引用。

🚑强引用(StrongReference)

在我们写的代码中,通过new关键字创建的对象就属于强引用。强引用是指如果强引用的关系还存在,那么垃圾回收器就不会回收掉被引用的对象。就算内存不足时,Java虚拟机就算抛出OOM异常,使程序异常终止,也不会随意回收强引用的对象来解决内存不足的问题。

🚒软引用(SoftReference)

软引用是指一些对象还有用,但不是必须的。内存足够的时候,软引用的对象不会被垃圾回收器回收,如果内存不足时,被软引用关联的对象,在系统将要发生内存溢出之前,该引用就会被列入回收范围之内,进行第二次回收,如果回收之后还没有足够的内存空间,则会抛出内存溢出异常。

🚚弱引用(WeakReference)

弱引用的强度比软引用的引用强度更弱。弱引用也是用来描述那些非必须的对象,不管当前内存是否足够,一旦虚拟机发现了只具有弱引用的对象,都会回收它的内存。被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。

🚛虚引用(PhantomReference)

虚引用是最弱的一种引用关系。持有弱引用的对象和没有任何引用差不多,在任何时候都可能会被垃圾回收器回收掉。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。
在这里插入图片描述

🚘Java中的类加载机制

Java的类加载机制是一个类从加载到虚拟机内存中开始,到卸载出内存,这个类会经历加载,验证,准备,解析,初始化,使用,卸载这七个阶段。其中,验证,准备,解析这三个阶段又被称为连接。

加载是整个类加载过程中的第一个阶段。在加载阶段,JVM需要完成三件事情:通过类的全限定名来获取定义此类的二进制字节流;将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构;在内存中生成一个代表这个类的Class对象,作为方法区这个类的各种数据的访问入口。

验证阶段大致上会完成下面四个阶段的检验动作:文件格式验证、元数据验证、字节码验证、符号引用验证。

准备阶段是正式为类中定义变量(静态变量)分配到内存并设置类变量初始值的阶段,这些变量所使用的内存都应当在方法区中进行分配,但必须注意到方法区本身是一个逻辑上的区域。

解析阶段是Java虚拟机将常量池内的符号替换为直接引用的过程,符号引用以一组符号来描述所引用的目标,直接引用是可以直接指向目标的指针、相对偏移量或者一个能间接定位到目标的句柄。

类的初始化阶段是类加载过程的最后一个步骤,直到初始化阶段,Java虚拟机才真正开始执行类中编写的Java程序代码,将主导权移交给应用程序。初始化阶段就是执行类构造器clinit方法的过程。clinit()并不是程序员在Java代码中直接编写的方法,它是Javac编译器的自动生成物。
在这里插入图片描述

🚜事务的隔离级别

读未提交(Read uncommitted)
一个事务可以读取另一个未提交事务的数据,最低级别,任何情况都无法保证。
读已提交(Read committed)
一个事务要等另一个事务提交后才能读取数据,可避免脏读的发生,会造成不可重复读
可重复读(Repeatable read) I
就是在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读的发生,但是会造成幻读,但MySQL采用MVCC(多并发版本控制)来避免脏读,不可重复读和幻读。
串行(Serializable)
是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用

Mysql的默认隔离级别是Repeatable read (可重复读)。

  1. 脏读:强调的是第二个事务读到的数据不够新
    栗子:假设老板今天给你发这个月的工资,本来要给你发2w元,结果手一抖发了20w元,这时老板还没有提交事务,而你查询到你的账户里多了20w元,老板总觉得不对劲,总感觉少了些什么,最后发现后回滚事务,给你发了2w,然后这时你打开账户发现只有2w块钱。
  2. 不可重复读:同一事务,两次读取到的数据不一样
    栗子:前提同第一个,老板给你发了2w元工资,你看到账户里多了2w块钱,此时老板觉得你这个月做的还不错,给你加了1w块钱奖励金并提交了事务,而此时你再次查询时发现是3w块钱,这就造成了在一个事务中读取到的事务不一致
  3. 幻读:重点在于新增数据库条数或删除数目,同样的条件,第一次和第二次读出来的记录数不一样
    栗子:和你相同薪资的人有10人,此时读数据读到的事务为10人,此时突然增加了一条工资和你们一样的人,提交事务后记录为11人,因此产生了幻读。
    在这里插入图片描述

🚖聚簇索引和非聚簇索引

聚簇索引是物理索引,数据表就是按顺序存储的,物理上是连续的。
一般情况下主键会默认创建聚簇索引
聚簇索引是将索引与数据放在一起,当你找到索引后,也就找到对应的数据了。每张表只能建立一个聚簇索引,但是该索引可以包含多个列(一般使用的是主键等不经常更新的列)

非聚簇索引:数据储存于索引分开,叶节点指针指向了对应的数据行。非聚簇索引也叫辅助索引,辅助索引访问数据时需要二次查找。辅助索引存储的不是行的物理位置,而是主键的值。而通过辅助索引首先找到的就是主键的值,再通过主键的值找到数据行对应的数据页,需要回表最后才能找到对应行。
在这里插入图片描述

🚍完全平方数

题目:

给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

示例 1:

输入:n = 12
输出:3
解释:12 = 4 + 4 + 4

示例 2:

输入:n = 13
输出:2
解释:13 = 4 + 9

思路:由于题目要求完全平方数的最少数量,因此至少要将能取到的数全部遍历一遍。那么对于本题而言,返回完全平方数最多的数量是多少呢,无疑是全部由1相加组成,因此最多的数量为n。而在遍历的过程中,如何才能知道是取当前的数,还是取比当前更合适的呢?因此我们需要保存临时的结果,不断地更新结果值。所以我们应该用动态规划的方法来解决这道题。

代码详解:

class Solution {
    public int numSquares(int n) {
        int []dp = new int[n+1]; //定义新数组,数组中的值均默认为0。
        for(int i=1;i<=n;i++){
            dp[i]=i;  //这里表示最差的情况,最差的情况一共有i个。
            for(int j=1;i-j*j>=0;j++){
                dp[i]=Math.min(dp[i],dp[i-j*j]+1);
            }
        }
        return dp[n];
    }
}

在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。