Skip to content

Commit a9dbda2

Browse files
committed
Update Java Notes
1 parent 71a47d1 commit a9dbda2

File tree

2 files changed

+70
-38
lines changed

2 files changed

+70
-38
lines changed

DB.md

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3648,7 +3648,7 @@ MERGE存储引擎:
36483648

36493649

36503650

3651-
## 索引优化
3651+
## 索引机制
36523652

36533653
### 索引介绍
36543654

@@ -4069,7 +4069,7 @@ B+Tree优点:提高查询速度,减少磁盘的IO次数,树形结构较小
40694069

40704070

40714071

4072-
### 优化方式
4072+
### 索引优化
40734073

40744074
#### 覆盖索引
40754075

@@ -4177,7 +4177,7 @@ CREATE INDEX idx_area ON table_name(area(7));
41774177

41784178

41794179

4180-
## 优化语句
4180+
## 语句优化
41814181

41824182
### 优化步骤
41834183

@@ -4317,12 +4317,12 @@ EXPLAIN SELECT * FROM table_1 WHERE id = 1;
43174317
MySQL执行计划的局限:
43184318

43194319
* EXPLAIN 不会告诉显示关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
4320-
* EXPLAIN 不考虑各种Cache
4321-
* EXPLAIN 不能显示MySQL在执行查询时所作的优化工作,因为执行计划在执行查询之前生成
4320+
* EXPLAIN 不考虑各种 Cache
4321+
* EXPLAIN 不能显示 MySQL 在执行查询时所作的优化工作,因为执行计划在执行查询之前生成
43224322
* EXPALIN 部分统计信息是估算的,并非精确值
4323-
* EXPALIN 只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划
4323+
* EXPALIN 只能解释 SELECT 操作,其他操作要重写为 SELECT 后查看执行计划
43244324
* 执行计划 在优化器之后、执行器之前生成,然后执行器调用存储引擎检索数据
4325-
* 执行计划可以随着底层优化器输入的更改而更改。EXPLAIN PLAN 显示的是在解释语句时数据库将如何运行SQL语句,由于执行环境和 EXPLAIN PLAN 环境的不同,此计划可能与SQL语句实际的执行计划不同
4325+
* 执行计划可以随着底层优化器输入的更改而更改。EXPLAIN PLAN 显示的是在解释语句时数据库将如何运行 SQL 语句,由于执行环境和 EXPLAIN PLAN 环境的不同,此计划可能与 SQL 语句实际的执行计划不同
43264326

43274327
环境准备:
43284328

@@ -4338,7 +4338,7 @@ MySQL执行计划的局限:
43384338

43394339
##### id
43404340

4341-
SQL执行的顺序的标识,SQL从大到小的执行
4341+
SQL 执行的顺序的标识,SQL 从大到小的执行
43424342

43434343
* id 相同时,执行顺序由上至下
43444344

@@ -4461,7 +4461,7 @@ key_len:
44614461
* Impossible where:说明 WHERE 语句会导致没有符合条件的行,通过收集统计信息不可能存在结果
44624462
* Select tables optimized away:说明仅通过使用索引,优化器可能仅从聚合函数结果中返回一行
44634463

4464-
* No tables used:Query 语句中使用from dual 或不含任何 from 子句
4464+
* No tables used:Query 语句中使用 from dual 或不含任何 from 子句
44654465

44664466

44674467

@@ -5017,7 +5017,7 @@ MySQL 4.1版本之后,开始支持SQL的子查询
50175017

50185018
#### OR
50195019

5020-
对于包含OR的查询子句,如果要利用索引,则OR之间的每个条件列都必须用到索引,而且不能使用到复合索引,如果没有索引,则应该考虑增加索引
5020+
对于包含OR的查询子句,如果要利用索引,则 OR 之间的每个条件列都必须用到索引,而且不能使用到复合索引,如果没有索引,则应该考虑增加索引
50215021

50225022
* 执行查询语句:
50235023

@@ -5122,7 +5122,7 @@ SQL提示,是优化数据库的一个重要手段,就是在SQL语句中加
51225122

51235123

51245124

5125-
## 优化系统
5125+
## 系统优化
51265126

51275127
### 应用优化
51285128

@@ -5424,9 +5424,9 @@ MySQL Server 是多线程结构,包括后台线程和客户服务线程。多
54245424

54255425

54265426

5427-
### 主从复制
5427+
## 主从复制
54285428

5429-
#### 基本介绍
5429+
### 基本介绍
54305430

54315431
复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步
54325432

@@ -5436,36 +5436,47 @@ MySQL 复制的优点主要包含以下三个方面:
54365436

54375437
- 主库出现问题,可以快速切换到从库提供服务
54385438

5439-
- 可以在从库上执行查询操作,从主库中更新,实现**读写分离**,降低主库的访问压力
5439+
- 可以在从库上执行查询操作,从主库中更新,实现读写分离
54405440

54415441
- 可以在从库中执行备份,以避免备份期间影响主库的服务
54425442

5443+
**读写分离**
5444+
5445+
* 读写分离可以降低主库的访问压力,提高系统的并发能力
5446+
* 主库不建查询的索引,从库建查询的索引。因为索引需要维护的,比如插入一条数据,不仅要在聚簇索引上面插入,对应的二级索引也得插入,修改也是一样的。所以将读操作分到从库了之后,可以在主库把查询要用的索引删了,减少写操作对主库的影响
5447+
54435448

54445449

54455450
***
54465451

54475452

54485453

5449-
#### 复制原理
5454+
### 复制原理
54505455

54515456
MySQL 的主从复制原理图:
54525457

54535458
![](https://gitee.com/seazean/images/raw/master/DB/MySQL-主从复制原理图.jpg)
54545459

5455-
主从复制需要三个线程**master(binlog dump thread)、slave(I/O thread 、SQL thread)**
5460+
主从复制主要依赖的是 binlog,MySQL 默认是异步复制,需要三个线程**master(binlog dump thread)、slave(I/O thread 、SQL thread)**
54565461

54575462
- binlog dump thread:在主库事务提交时,负责把数据变更作为事件 Events 记录在二进制日志文件 binlog 中,并通知 slave 有数据更新
54585463
- I/O thread:负责从主服务器上拉取二进制日志,并将 binlog 日志内容依次写到 relay log 文件的最末端,并将新的 binlog 文件名和 offset 记录到 master-info 文件中,以便下一次读取master 端新 binlog 日志时能告诉 master 服务器从新 binlog 日志的指定文件及位置开始读取新的 binlog 日志内容
54595464
- SQL thread:监测本地 relay log中新增了日志内容,读取中继日志并重做其中的 SQL 语句
54605465
- 从库在 relay-log.info 中记录当前应用中继日志的文件名和位置点以便下一次数据复制
54615466

5467+
同步与异步:
5468+
5469+
* 异步复制有数据丢失风险,例如数据还未同步到从库,主库就给客户端响应,然后主库挂了,此时从库晋升为主库的话数据是缺失的
5470+
* 同步复制,主库需要将 binlog 复制到所有从库,等所有从库响应了之后才会给客户端响应,这样的话性能很差,一般不会选择同步复制
5471+
* MySQL 5.7 之出现了半同步复制,有参数可以选择成功同步几个从库就返回响应
5472+
54625473

54635474

54645475
****
54655476

54665477

54675478

5468-
#### 主从延迟
5479+
### 主从延迟
54695480

54705481
主从延迟就是主从之间是存在一定时间的数据不一致:
54715482

@@ -5488,21 +5499,23 @@ MySQL 的主从复制原理图:
54885499

54895500
主从同步问题永远都是一致性和性能的权衡,需要根据实际的应用场景,可以采取下面的办法:
54905501

5502+
* 二次查询,如果从库查不到数据,则再去主库查一遍,由 API 封装,比较简单,但导致主库压力大
54915503
* 降低多线程大事务并发的概率,优化业务逻辑
5492-
* 优化SQL,避免慢SQL,减少批量操作
5504+
* 优化 SQL,避免慢 SQL,减少批量操作
54935505
* 提高从库机器的配置,减少主库写 binlog 和从库读 binlog 的效率差
54945506
* 尽量采用短的链路,主库和从库服务器的距离尽量要短,提升端口带宽,减少 binlog 传输的网络延时
54955507
* 实时性要求的业务读强制走主库,从库只做灾备,备份
5508+
* 强制将写之后立马读的操作转移到主库,比如刚注册的用户,直接登录从库查询可能查询不到,先走主库登录
54965509

54975510

54985511

54995512
****
55005513

55015514

55025515

5503-
#### 搭建流程
5516+
### 搭建流程
55045517

5505-
##### master
5518+
#### master
55065519

55075520
1. 在master 的配置文件(/etc/mysql/my.cnf)中,配置如下内容:
55085521

@@ -5562,7 +5575,7 @@ MySQL 的主从复制原理图:
55625575

55635576

55645577

5565-
##### slave
5578+
#### slave
55665579

55675580
1. 在 slave 端配置文件中,配置如下内容:
55685581

@@ -5601,7 +5614,7 @@ MySQL 的主从复制原理图:
56015614

56025615

56035616

5604-
##### 验证
5617+
#### 验证
56055618

56065619
1. 在主库中创建数据库,创建表并插入数据:
56075620

@@ -7883,7 +7896,7 @@ Redis 自身是一个 Map,其中所有的数据都是采用 key : value 的形
78837896

78847897
### 线程模型
78857898

7886-
Redis 基于 Reactor 模式开发了网络事件处理器,这个处理器被称为文件事件处理器(file event handler),这个文件事件处理器是单线程的,所以Redis叫做单线程的模型
7899+
Redis 基于 Reactor 模式开发了网络事件处理器,这个处理器被称为文件事件处理器(file event handler),这个文件事件处理器是单线程的,所以 Redis 叫做单线程的模型
78877900

78887901
文件事件处理器以单线程方式运行,但是使用 I/O 多路复用程序来监听多个套接字,既实现了高性能的网络通信模型,又很好地与 Redis 服务器中其他同样以单线程方式运行的模块进行对接,保持了 Redis 单线程设计的简单性
78897902

@@ -10831,7 +10844,7 @@ Cache Aside Pattern 中服务端需要同时维系 DB 和 cache,并且是以 D
1083110844
1083210845
数据库和缓存数据强一致场景 :更新DB的时候同样更新 cache,不过需要加一个锁来保证更新 cache 时不存在线程安全问题,这样可以增加命中率
1083310846
10834-
可以短暂地允许数据库和缓存数据不一致场景 :更新DB的时候同样更新 cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致影响也比较小
10847+
可以短暂地允许数据库和缓存数据不一致场景:更新DB的时候同样更新 cache,但是给缓存加一个比较短的过期时间,这样的话就可以保证即使数据不一致影响也比较小
1083510848
1083610849
1083710850

Java.md

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,8 @@ System.out.println(x == y); // false
316316

317317
语法:`Scanner sc = new Scanner(System.in)`
318318

319-
* next():遇到了空格, 就不再录入数据了 , 结束标记: 空格, tab键
320-
* nextLine():可以将数据完整的接收过来 , 结束标记: 回车换行符
319+
* next():遇到了空格就不再录入数据了结束标记:空格、tab键
320+
* nextLine():可以将数据完整的接收过来结束标记回车换行符
321321

322322
一般使用 `sc.nextInt()` 或者 `sc.nextLine()` 接受整型和字符串,然后转成需要的数据类型
323323

@@ -327,10 +327,10 @@ print:`PrintStream.write()`
327327
> 使用引用数据类型的API
328328

329329
```java
330-
import java.util.Scanner;
331-
public class ScannerDemo {
332-
public static void main(String[] args) {
333-
Scanner sc = new Scanner(System.in);
330+
public static void main(String[] args) {
331+
Scanner sc = new Scanner(System.in);
332+
while (sc.hasNextLine()) {
333+
String msg = sc.nextLine();
334334
}
335335
}
336336
```
@@ -7645,7 +7645,7 @@ fw.close;
76457645

76467646
#### 缓冲流
76477647

7648-
##### 概述
7648+
##### 基本介绍
76497649

76507650
作用:缓冲流可以提高字节流和字符流的读写数据的性能。
76517651

@@ -12131,7 +12131,7 @@ public class Demo1_27 {
1213112131

1213212132
虚拟机采用了两种方式在创建对象时解决并发问题:CAS、TLAB
1213312133

12134-
TLAB:Thread Local Allocation Buffer,为每个线程在堆内单独分配了一个缓冲区,多线程分配内存时,使用TLAB可以避免线程安全问题,同时还能够提升内存分配的吞吐量,这种内存分配方式叫做**快速分配策略**
12134+
TLAB:Thread Local Allocation Buffer,为每个线程在堆内单独分配了一个缓冲区,多线程分配内存时,使用TLAB 可以避免线程安全问题,同时还能够提升内存分配的吞吐量,这种内存分配方式叫做**快速分配策略**
1213512135

1213612136
- 栈上分配使用的是栈来进行对象内存的分配
1213712137
- TLAB 分配使用的是 Eden 区域进行内存分配,属于堆内存
@@ -12142,7 +12142,7 @@ TLAB:Thread Local Allocation Buffer,为每个线程在堆内单独分配了
1214212142

1214312143
![](https://gitee.com/seazean/images/raw/master/Java/JVM-TLAB内存分配策略.jpg)
1214412144

12145-
JVM是将TLAB作为内存分配的首选,但不是所有的对象实例都能够在TLAB中成功分配内存,一旦对象在TLAB空间分配内存失败时,JVM就会尝试着通过**使用加锁机制确保数据操作的原子性**,从而直接在Eden空间中分配内存
12145+
JVM 是将 TLAB 作为内存分配的首选,但不是所有的对象实例都能够在 TLAB 中成功分配内存,一旦对象在TLAB空间分配内存失败时,JVM 就会通过**使用加锁机制确保数据操作的原子性**,从而直接在 Eden 空间中分配内存
1214612146

1214712147
栈上分配优先于 TLAB 分配进行,逃逸分析中若可进行栈上分配优化,会优先进行对象栈上直接分配内存
1214812148

@@ -19363,6 +19363,27 @@ public class JdbcUtils {
1936319363
}
1936419364
```
1936519365

19366+
用 ThreadLocal 使 SimpleDateFormat 从独享变量变成单个线程变量:
19367+
19368+
```java
19369+
public class ThreadLocalDateUtil {
19370+
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>() {
19371+
@Override
19372+
protected DateFormat initialValue() {
19373+
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
19374+
}
19375+
};
19376+
19377+
public static Date parse(String dateStr) throws ParseException {
19378+
return threadLocal.get().parse(dateStr);
19379+
}
19380+
19381+
public static String format(Date date) {
19382+
return threadLocal.get().format(date);
19383+
}
19384+
}
19385+
```
19386+
1936619387

1936719388

1936819389
****
@@ -19679,7 +19700,7 @@ Memory leak:内存泄漏是指程序中动态分配的堆内存由于某种原
1967919700

1968019701
* 如果key使用弱引用:
1968119702

19682-
使用完 ThreadLocal ,threadLocal Ref 被回收,ThreadLocalMap 只持有 ThreadLocal 的弱引用,所以threadlocal 也可以被回收,此时Entry中的 key=null。但没有手动删除这个Entry或者 CurrentThread 依然运行,依然存在强引用链,value不会被回收,而这块value永远不会被访问到,导致value内存泄漏
19703+
使用完 ThreadLocal ,threadLocal Ref 被回收,ThreadLocalMap 只持有 ThreadLocal 的弱引用,所以threadlocal 也可以被回收,此时 Entry 中的 key=null。但没有手动删除这个 Entry 或者 CurrentThread 依然运行,依然存在强引用链,value 不会被回收,而这块 value 永远不会被访问到,导致 value 内存泄漏
1968319704

1968419705
<img src="https://gitee.com/seazean/images/raw/master/Java/JUC-ThreadLocal内存泄漏弱引用.png" style="zoom:67%;" />
1968519706

@@ -25240,10 +25261,8 @@ UML 从目标系统的不同角度出发,定义了用例图、类图、对象
2524025261

2524125262
```java
2524225263
public final Object readObject() throws IOException, ClassNotFoundException{
25243-
int outerHandle = passHandle;
25244-
try {
25245-
Object obj = readObject0(false);//重点查看readObject0方法
25246-
}
25264+
//...
25265+
Object obj = readObject0(false);//重点查看readObject0方法
2524725266
}
2524825267

2524925268
private Object readObject0(boolean unshared) throws IOException {

0 commit comments

Comments
 (0)