JVM的内存结构在JDK1.8有所改变,本文简述JDK1.8的内存结构。
在JDK1.8中,JVM的内存结构主要分为两大块:
一、线程共享根据数据区域的不同,可分为两部分:
1.运行时数据区域
堆
Java 虚拟机所管理的内存中最大的一块,Java 堆是所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,“几乎”所有的对象实例以及数组都在这里分配内存。
运行时常量池
字符串常量池位于堆中(JDK1.7及之后),是 JVM 为了提升性能和减少内存消耗针对字符串(String 类)专门开辟的一块区域,主要目的是为了避免字符串的重复创建。
12345// 创建字符串对象”ab“,会在堆中将字符串对象”ab“的引用保存在字符串常量池中String aa = "ab";// 直接返回字符串常量池中字符串对象”ab“的引用String bb = "ab";System.out.println(aa==bb);// true,这里比较的是地址而不是值,即代表两者指向同一对象
Java 6及之前的版本中,字符串常量池 ...
一、可变性1.String是不可变的原因:
1.(数组final)保存字符串的数组被 final 修饰且为私有的,并且String 类没有提供/暴露修改这个字符串的方法。
2.(类final)String 类被 final 修饰导致其不能被继承,进而避免了子类破坏 String 不可变。
1234567891011public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /*Java8及以前的版本,使用char数组存储*/ private final char value[]; //... /*Java9及以后的版本,改用byte数组存储*/ // @Stable 注解表示变量最多被修改一次,称为“稳定的”。 @Stable private final byte[] value; //...}
Java 9 为何要将 String 的底层实现由 char[] ...
基本数据类型
占用字节
默认值
包装类型
byte
1
0
Byte
short
2
0
Short
int
4
0
Integer
long
8
0L
Long
float
4
0f
Float
double
8
0d
Double
char
2
‘u0000’
Character
bool
1
false
Boolean
‘u0000’:\u代表是一个Unicode字符,0000表示空字符
一、原子性问题原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
一个很经典的例子就是银行账户转账问题:
比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。
试想一下,如果这2个操作不具备原子性,会造成什么样的后果。假如从账户A减去1000元之后,操作突然中止。然后又从B取出了500元,取出500元之后,再执行 往账户B加上1000元 的操作。这样就会导致账户A虽然减去了1000元,但是账户B没有收到这个转过来的1000元。
所以这2个操作必须要具备原子性才能保证不出现一些意外的问题。
同样地反映到并发编程中会出现什么结果呢?
举个最简单的例子,大家想一下假如为一个32位的变量赋值过程不具备原子性的话,会发生什么后果?
假若一个线程执行到这个语句时,我暂且假设为一个32位的变量赋值包括两个过程:为低16位赋值,为高16位赋值。
那么就可能发生一种情况:当将低16位数值写入之后,突然被中断,而此时又有一个线程去读取i的值,那么读取到的就是错误的数据。
二、可见性问题可见性:指当多个线程访问同 ...
1.完全备份(全量备份) 关于数据库备份的常见方式有哪些,网络文献说法不一,这里取牛客上的《小红书24秋招后端开发》第4题中,官方解析中提供的说法:常见的备份方式有三种:完全备份、差异备份、增量备份。
一、完全备份(全量备份) 完全备份(Full Backup)就是指对某一个时间点上的所有数据或应用进行的一个完全拷贝。备份全部选中的文件夹,并不依赖文件的存档属性来确定备份哪些文件。实际应用中就是用一盘磁带对整个系统进行完全备份,包括其中的系统和所有数据。
在备份过程中,任何现有的标记都被清除,每个文件都被标记为已备份。换言之,清除存档属性。
存档属性:个人理解为给文件设置一个属性为“待存档”,即用来标记一个文件在被修改后还未被备份过。
注意,只有完全备份才会清除文档属性,差异备份和增量备份都不会清除文档属性。
优点:只要用一盘磁带,就可以恢复丢失的数据。因此大大加快了系统或数据的恢复时间。
缺点:
各个全备份磁带中的备份数据存在大量的重复信息
由于每次需要备份的数据量相当大,因此备份时间较长
二、增量备份 增量备份(Incremental Backup )是 ...
一、final(修饰符)根据修饰的对象不同,有不同的效果。但其本质上表示一种最终状态,即一个不可改变的实体,只能被分配一次。
修饰对象
效果
类
不能被继承,final类中的方法默认也是final
方法
不能被重写,private类型的方法默认是final的
成员变量
不能被重新赋值,即常量(必须在声明的同时赋值)
二、finally(总是执行)一般作用在try-catch代码块中形成try-catch-finally代码块。finally代码块中放置一些必须执行的代码,即不论是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
但由于finally用法的特殊性,即使在try-catch代码块中执行了return语句,其会撤销之前的return语句,继续执行最后的finally代码块中的代码;
注意:如果在try语句块中执行了System.exit (0) 语句,即直接终止了Java虚拟机的运行,所以finally语句块不会执行;
三、finalize()(一个GC方法)finalize()是Java中的一个方法名,Java使用finalize( ...
一、重写(实现过程不同)是子类对父类允许访问的方法的实现过程的重新编写。
方法名、参数列表必须相同,子类方法返回值类型应比父类方法返回值类型更小或相等,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
“两同两小一大”
如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。
构造方法无法被重写
二、重载(参数列表不同)在同一个类中(或者父类和子类之间),方法名必须相同,参数列表一定不同(类型、个数、顺序,三者一个或多个不同),方法返回值和访问修饰符可以不同。
三、记忆方法函数是道题,重写写过程,重载改题目(参数)。
重写写过程:一道题做错了老师要求重写,当然是重新写解题过程
重载改题目(参数):重新写了正确的解题过程后想要找一道类似的题目练练手,改下题目的参数是最简单的办法了。重载->重新加载,重新加载一道新题来写,题目(参数)肯定不一样。
一、共同点
都可以使线程暂停执行: wait() 方法和 sleep() 方法都可以使当前线程暂停执行一段时间。
都可以用于多线程编程: 无论是 wait() 还是 sleep(),都可以在多线程环境中使用。
都可以在同步块或同步方法中使用: wait() 方法通常与 synchronized 关键字一起使用,因为它需要在同步块或同步方法中调用。而 sleep() 方法可以在任何地方使用,不受同步的限制。
都可以捕获 InterruptedException 异常: 调用 wait() 或 sleep() 方法时,都可能抛出 InterruptedException 异常,因此在使用这两个方法时都需要处理这个异常。
二、不同点
sleep
wait
所属类
Thread 线程类
Object 顶级类
方法类型
静态方法
普通方法
释放对象锁
否
是
调用后状态
让出CPU给其他线程,但是他的监控状态依然保持
进入等待此对象的等待锁定池
恢复运行条件
设定的时间到后自动苏醒
未指定超时时间时,不会自动苏醒,需要别的线程调用同一个对象上的 notify()或者 ...
我们常用的关系型数据库(如:MySQL、SQL Server 等)事务都有 ACID 特性,每个字母分别代表的意义如下:
原子性(Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
一致性(Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
隔离性(Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
持久性(Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
另外,只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。
简单而言: A、I、D 是手段,C 是目的。
一、缓存穿透的定义缓存穿透: 指客户端请求的数据在Redis缓存和数据库中都不存在,这样Redis缓存将永远不会生效,也就是说请求都会打到数据库中。
如果有心人利用这一特性对服务器同时进行大量请求,就有可能造成数据库的奔溃,因此,我们需要对缓存穿透进行处理。
二、常见解决方案1.缓存空对象即客户端请求的数据如果在缓存和数据库中都不存在,我们也在Redis中进行缓存,设置value为null。
优点: 实现简单,维护方便。缺点:①大量的空值会造成额外的内存消耗由于我们将不存在的数据都存入Redis缓存中并置为null,如此大量的空值会占据较多的内存空间,造成内存的浪费。
解决方法: 对每一个空数据都设置较短过的期时间(TTL),可以是一两分钟或者适当的时间。这样可以保证每一个空数据只存在一定的时间就会被删除,减少内存空间的占用。
②造成短期的数据不一致假设用户请求了一个不存在的id数据,根据缓存空对象的处理办法,我们向Redis中插入了null值并设置了TTL过期时间。如果这时我们向数据库插入了一条id的数据,而该id恰好与刚刚用户请求的id一致,那么,在TTL到期之前,所有用户请求这 ...



























