当年,学姐把这份Java总结给我,让我在22k的校招王者局乱杀_java一个栈帧占多少字节

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

**.Executor**

为什么使用线程池:手动创建线程耗费性能,不利于管理。

首先创建线程池有两种方式:使用Executors工厂来创建ThreadPoolExecutor这类自定义线程池。

1. 使用Executors工厂来创建

Executors是一个类,用来创建线程池,常用的有四种线程池

1.newFixedThreadPool 创建一个可重复固定的线程数的线程池

2.newCachedThreadPool 创建一个可缓存的线程池,调用execute将重复用以前构造的线程(如果当前线程可用)。如果没有可用线程则创建新的线程并加入到池中。终止并从缓存中移除那些已有60s未被使用的线程。

3.newSingleThreadExecutor创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行

  1. newScheduledThreadPool 创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

使用示例:

2. 使用ThreadPoolExecutor这个类自定义创建线程池

**.ThreadLocal**

https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/6782674c-1bfe-4879-af39-e9d722a95d39.png

**.**中断线程

1.线程执行完毕会自动结束

2.在线程处于阻塞,期限等待火无期限等待时,调用线程的interrupt()会抛出interruptedException异常从而提前终止线程

3.若没有处于阻塞状态,调用interrupte()将线程标记为中断,此时在调用interrupted()判断线程是否处于中断状态,来提前终止线程。

4.线程池调用shutdown()等待所有线程执行完毕之后关闭

**.Volatile****关键字的理解**

两层语义:1.保证不同线程对该变量的内存可见线

2.禁止进行指令重排序

内存语义:

读这个变量的时候,JMM会把本地内存中的变量设置为无效,从主内存中取;

写这个变量的时候,JMM会把本地内存变量刷新到主内存当中

实现:添加Volatile关键字会在汇编代码中多处一个kock前指令,也就是内存屏障

**.Synchronized****关键字**

(1)synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

3. 修饰一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

  1. 修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

(2)Synchronized的作用主要有三个:(1)确保线程互斥的访问同步代码(2)保证共享变量的修改能够及时可见(3)有效解决重排序问题。

(3)Synchronized 原理

在编译的字节码中加入了两条指令来进行代码的同步。

monitorenter :

每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

1.如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。

2.如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.

3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。

monitorexit:

执行monitorexit的线程必须是objectref所对应的monitor的所有者。

指令执行时,monitor的进入数减1,如果减1后进入数为0,那线程退出monitor,不再是这个monitor的所有者。其他被这个monitor阻塞的线程可以尝试去获取这个 monitor 的所有权。

通过这两段描述,我们应该能很清楚的看出Synchronized的实现原理,Synchronized的语义底层是通过一个monitor的对象来完成,其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。

(4)Synchronized的优化

(4)synchronized与Lock的区别

lock是一个类,主要有以下几个方法:

lock():获取锁,如果锁被暂用则一直等待

unlock():释放锁

tryLock(): 注意返回类型是boolean,如果获取锁的时候锁被占用就返回false,否则返回true

tryLock(long time, TimeUnit unit):比起tryLock()就是给了一个时间期限,保证等待参数时间

https://note.youdao.com/yws/public/resource/cc25598bbaff18a55569c256de4cf1c6/xmlnote/10A95AB8238442569108FC93755C91FF/1701

(1)Lock的加锁和解锁都是由java代码实现的,而synchronize的加锁和解锁的过程是由JVM管理的。

(2)synchronized能锁住类、方法和代码块,而Lock是块范围内的。

(3)Lock能提高多个线程读操作的效率;

(4)Lock:Lock实现和synchronized不一样,后者是一种悲观锁,它胆子很小,它很怕有人和它抢吃的,所以它每次吃东西前都把自己关起来。而Lock底层其实是CAS乐观锁的体现,它无所谓,别人抢了它吃的,它重新去拿吃的就好啦,所以它很乐观。如果面试问起,你就说底层主要靠volatile和CAS操作实现的。

**.CAS****机制**

Compare And Swap

CAS操作是一个原子操作,由一条CPU指令完成,使用了3个基本操作数,内存地址V,旧的预期值A ,要修改的新值B

需要更新一个变量的时候,只有当内存地址V中的值和预期值A相等的时候才会修改为新值B ,如果失败则自旋,重新尝试

问题:

1.ABA 解决办法,加一个版本号,只有当版本号和预期值都符合的时候才修改

2.不能保证代码块的原子性,CAS机制知识保证一个变量的原子操作

**.JMM****的理解**

JMM的核心是找到一个平衡点,在保证内存可见性的前提下,尽量的放松对编译器和处理器重排序的限制。

可能会产生缓存一致性的问题:

1.总线锁定

2.缓存一致性协议

三大特性:原子性,可见性,有序性

**.JVM****的锁优化**

1.自旋锁和自适应自旋锁

线程挂起和恢复都需要很大的性能开销,很多共享数据的锁定状态只持续很短的时间,为这段时间挂起恢复不值得,所以可以让现场进入一个自旋状态,但仍占用cpu的时间,默认是10次,超过10次则采用传统的方式挂起线程。自适应自旋锁会根据上次在这个锁上自旋的时间调整自选次数

2.锁消除

检测到对局部变量加锁,会自动将锁消除,如在一个方法里面有sb = s1 + s2 + s3以前会转化为StringBuffer(线程安全,有加锁)的append操作,优化之后会转换成StringBuilder的sppend操作

3.锁粗化

对一个对象反复加锁解锁,如上述的append方法,编译器会优化,只在最外层加一个锁

4.轻量级锁

对象有一个对象头,对象头分两部分区域,一部分存储子树的hashcode,GC分代年龄,锁标志位等,官方成为mark word,另一部分用于存储指向方法区对象类型的指针;

轻量级锁的执行过程是代码进入同步块的时候,如果当前对象没有被锁定(锁标志为是01)则先在线程的栈帧中建立一个锁记录空间(lock record)将对象的mark word拷贝过来,然后利用cas操作尝试将对象的markword更新为指向lock record,如果成功则当前线程拥有该对象锁,并且将锁标志位从01改为00,如果更新失败则会检查当前对象markword是否指向当前线程的栈帧,如果是则直接进入同步块执行否则说明当前的对象锁已经被其他线程占有。如果有两条以上的线程竞争这个锁,那就会膨胀成重量级锁,锁标志为变成10;

5.偏向锁

锁对象第一次被线程获取的时候,会将当前的锁标志设置为偏向锁01状态,并使用cas操作将当前线程的id记录在markword当中,如果成功那么在以后的操作当中不需进行任何操作就可以进入同步代码块,当有另外一个线程获取当前锁的时候,偏向模式就宣告结束,撤销偏向锁之后恢复到未锁定或者轻量级锁状态

JAVA****基础

String

1.string s1 = “aaa” 与 String s1 = new String(aaa);

前者会在Stringpool中创建一个对象,如果Stringpool中已经有了,则直接引用

后者会在Stringpool和堆中分别创建一个对象,如果StringPool中已经有了则只创建一个对象

2.调用s1.integer()方法,可以将字符串放入StringPool中,如果已经存在则直接返回这个对象

继承

**1.**几种修饰符的访问权限范围

2. ==  equals  hashcode****的关系

1.==是比较两个对象的地址是否相等

2.equals默认和 == 一样也是比较地址,也可以根据自己的需求来重写什么叫做相等

3.hashcode 是根据对象的地址来返回一串int型数字,如果对象不一样的话返回的值也不一样

3.为什么重写equals的同时也要重写hashcode

首先必须满足如果equals相同,那么hashcode也必须相同,如果hashcode不相同,那么equals必须不相同的原则,否则会导致该类无法与基于散列值的集合类(hashmap , hashset ,hashtable)结合正常运行

因为对于这些集合在进行重复性判断时,是先用hashcode判断,如果相同在用equals判断

4.hash****冲突的解决方法

1.开放地址法(线性探测法,二次探测法)

2.在散列函数法

3.链地址法

5.hashtable与hashmap的区别

1.hashmap线程不安全,hashtable线程安全

2.hashmap最多允许一个键为null,而hashtable不允许

3.hashtable中默认的hash数组大小为11,增加的方式是old*2+1,而hashmap默认是16,肯定是2的指数

4.计算hash的方法不一样,hashtable是直接用hashcode,而hashmap使用了key的高16位和低16位做异或运算

Linkedhashmap继承于hashmap,可以按顺序读取,底层使用的是双向链表

TreeMap实现了sortmap接口,可以对元素进行排序,底层使用的红黑树

7.java BIO NIO AIO 序列化

字节操作:使用inputStream和outPutSream实现,字节是传输和存储的最小单位

字符操作:inputStreamReader:将字节流解码成字符流

OutPutStramWriter:将字符流编码成字节流

对象操作:序列化就是将对象转换成字节序列,方便存储和运输,两个用途:

1.把对象的字节序列永久地保存到硬盘中,通常存放在一个文件里

2.在网络上传送对象的字节序列

在很多应用中,需要对某些对象进行序列化,让他们离开内存空间,入住到物理磁盘方便长期保存,比如session对象,当有大量用户并发访问的时候可能会出现10万个session对象,内存吃不消,此时就需要将这些session先序列化到硬盘中,等要用的时候在把对象还原到内存中。

当两个进程在进行远程通信的时候,彼此可以发送各种类型的数据,无论是何种类型的数据,都会以二进制的序列在网络上传送。发送方需要把这个java对象转换成字节序列,才能在网络上传送;接收方则需要把字节序列恢复成java对象。

Io与NIO的区别:

1.NIO是非阻塞的

2.NIO是面向缓冲区的,IO是面向流的

AIO:异步非阻塞

8.static关键字的作用

一.修饰变量:

1.静态变量在类加载的时候被创建并初始化,只被创建一次(类加载只进行一次),可以修改

2.静态变量属于整个类而不属于某个对象。

二.修饰方法

1.可以通过类名来访问,不需要创建对象来访问,可以用来实现单例模式

2.静态方法只能调用静态方法和静态变量

三.修饰静态代码块

在类加载的时候执行,且只执行一次

9.单例模式

实现:

1.为什么要用判断双重:
因为可能有两个线程都执行完了第一个if语句,如果没有第二重判断,那么当其中有个线程执行完synchronized里面的语句之后,另外一个线程跟着也会执行,这样就达不到单例模式的效果

2.第一重判断去掉也可以实现,为什么不去掉

这个设计性能问题,因为

参考:https://qinjiangbo.com/mechanism-of-double-locking-check.html

10.this与super关键字

9.java中的多态

分为两种:

1.编译时多态:体现在重载(方法名相同而参数不同),在编译时期就根据传入的参数确定好调用哪个方法;

2.运行时多态:体现在方法的重写。在运行时期判断引用类型的实际类型根据实际的类型调用其相应的方法;

当父类对象引用变量引用子类对象时,被引用对象的类型决定了调用谁的成员方法,引用变量类型决定可调用的方法。如果子类中没有覆盖该方法,那么会去父类中寻找。

参考链接:https://www.runoob.com/w3cnote/java-polymorphism.html

10.接口类和抽象类的异同

区别:

1.抽象类可以有非抽象方法,但接口只能有抽象方法

2.接口中的成员变量默认修饰为public static final(高度抽象的模版,所以这些都是提取出来的不变特征),方法默认修饰为public abstract。抽象类中的成员变量可以被不同的修饰符来修饰

3.类可以实现多个接口但只能继承一个抽象类

相同:

1.不能被实例化

2.派生类都必须实现未实现的方法

11.instanceof

用来判断一个对象是否是一个类的实例

12.各种排序算法复杂度及稳定性

1.java底层如何实现排序的

Java中Arrays.sort使用了两种排序方法,快速排序和优化归并排序。

快速排序主要针对基本的数据类型(int short long)排序,而归并排序用于对象类型的排序

如果数据量小于60会使用插入排序,插入排序是稳定的

13.java中的堆和栈

栈:主要用于存储局部变量和对象的引用变量,每个线程都有一个独立的栈空间,所以线程之间是不共享数据的;

栈的特点是存取速度快,但所存数据的大小和生存期必须是确定的(编译后就已经确定大小)

堆:堆中主要存储实例化的对象和数组。线程共享。堆的优势是可以动态的分配内存大小,生存期也不必事先告诉编译器,但缺点是存取速度较慢

Linux基本面试题:

Ls:用于显示指定工作目录下的类容,不会列出详细信息

Ll:会列出当前文件目录的详细信息,含有时间,权限,大小等

Cd:用于切换到目标目录

Mkdir:用于简历当前目录的子目录

rm-r 删除的文件或者目录,需确认

rm –rf同上但无需确认

cp:复制文件 若复制目录则必须加上-r

数据库****MySQL

**.**索引

1.B树,B+树,以及两者的区别

B树是一种多路平衡查找树,其每一个节点都存储Key和data

B+树是B树的一个变种,叶子节点存储data,非叶子节点只存储key,B+树的叶子节点增加了顺序访问指针,每一个叶子节点都可以访问到他的下一个叶子节点

区别:

1.B+树种只有叶子节点会带有全部信息,非叶子节点只起到索引的作用,二B树的所有节点都带有全部信息,B+树的每一层节点都会再次出现在下一层节点上

2.B+树种所有叶子节点都是通过指针连在一起,B树则没有

2.索引的优点和缺点

优点:可以加大检索速度

缺点:创建和维护索引需要耗费时间

3.Mysql为什么选择B+树

Mysql数据本质上是放在外部存储的,B+树是为了加快读取速度二设计的一种数据结构

1.可以减少i/o次数,只有叶子节点才存储数据,非叶子节点存储索引,这样一次读取到内存的关键字增多,相对i/o次数也就减少(根据区别一)

2.能够提供稳定高效的范围扫描,因为所有的叶子节点都互相连接(根据区别二)

4.索引越多越好吗?

索引可以提高select的效率,但是也降低了insert和updata的效率,因为插入和更新的时候可能会重建索引,索引怎么建索引要慎重考虑。

5.索引分类

1.B+树索引:以b+树作为数据结构的索引

2.hash索引:能以O(1)的时间复杂度查找,但失去了有序性,innodb有一个自适应哈希索引,当这个索引值被频繁使用时会在b+树上创建一个哈希索引

3.全文索引:用于查找文本的关键词,中文需要由中文分词插件

**. MySQL****优化**

一.MySQL的优化,主要分为索引的的优化,sql语句的优化,表的优化。同时可以使用缓存增加效率

1.索引的优化

只要列中含有null,最好不要再此列设置索引

对于经常在where语句中使用的列,最好设置一个索引

对于like语句,以%或者-开头的不会使用索引,以%结尾会使用索引

二.sql语句的优化

查询优化要尽量避免全表扫描

查询时能不用*就不用*,尽量写字段名

**. MySQL****常问问题**

1.数据库如何应对大规模的写入和读取

(1)使用NoSQL,通过降低数据的安全性,减少对事物的支持,减少复杂查询的支持来获取性能的提升;但有些场合NoSQL无法满足要求

(2)分库分表:

水平切分:不修改数据库的表结构,通过对表中的数据拆分而达到分片的目的,一般水平切分在查询的时候可能会用到union操作(多个结果并)

可以根据hash或者日期来进行分表

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

索引

3.全文索引:用于查找文本的关键词,中文需要由中文分词插件

**. MySQL****优化**

一.MySQL的优化,主要分为索引的的优化,sql语句的优化,表的优化。同时可以使用缓存增加效率

1.索引的优化

只要列中含有null,最好不要再此列设置索引

对于经常在where语句中使用的列,最好设置一个索引

对于like语句,以%或者-开头的不会使用索引,以%结尾会使用索引

二.sql语句的优化

查询优化要尽量避免全表扫描

查询时能不用*就不用*,尽量写字段名

**. MySQL****常问问题**

1.数据库如何应对大规模的写入和读取

(1)使用NoSQL,通过降低数据的安全性,减少对事物的支持,减少复杂查询的支持来获取性能的提升;但有些场合NoSQL无法满足要求

(2)分库分表:

水平切分:不修改数据库的表结构,通过对表中的数据拆分而达到分片的目的,一般水平切分在查询的时候可能会用到union操作(多个结果并)

可以根据hash或者日期来进行分表

[外链图片转存中…(img-IScDouDt-1715807200744)]
[外链图片转存中…(img-fkzXZPog-1715807200744)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值