This commit is contained in:
lostecho
2024-05-13 20:50:11 +08:00
parent 432ac9ba42
commit 0e31c0d985
20 changed files with 5426 additions and 187 deletions

View File

@@ -1,5 +1,8 @@
[ [
"easy-typing-obsidian", "easy-typing-obsidian",
"cm-editor-syntax-highlight-obsidian", "cm-editor-syntax-highlight-obsidian",
"markdown-prettifier" "markdown-prettifier",
"obsidian42-brat",
"attachment-flow-plugin",
"remotely-save"
] ]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"id":"attachment-flow-plugin","name":"AttachFlow","version":"0.4.3","minAppVersion":"1.0.9","description":"This nifty plugin enables seamless management of attachments and referenced links directly from your documents. Taking advantage of an intuitive right-click menu, you can efficiently handle resources in both LIVE and READ modes.","author":"yaozhuwa","authorUrl":"https://github.com/Yaozhuwa","isDesktopOnly":false,"fundingUrl":"https://www.buymeacoffee.com/yaozhuwa"}

View File

@@ -0,0 +1,46 @@
.attachment-flow-center-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
}
.attachment-flow-log {
margin-bottom: 13px;
margin-top: 5px;
white-space: pre-line; /* enable line break when html parse text containing '\n' */
}
button.mod-warning {
background-color: var(--background-modifier-error);
color: var(--text-on-accent);
}
.af-scale-div {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
color: #fff;
font-family: var(--default-font);
font-size: 20px;
background: rgba(0, 0, 0, 0.5);
padding: 5px;
}
.image-ready-resize {
cursor: nwse-resize;
outline: 6px solid #dfb0f283;
}
.image-ready-click-view {
cursor: zoom-in;
}
.image-in-drag-resize {
border: 2px solid blue;
box-sizing: border-box;
}
/* 点击查看的大图 */
#af-zoomed-image {
cursor: move;
}

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
{ {
"id": "easy-typing-obsidian", "id": "easy-typing-obsidian",
"name": "Easy Typing", "name": "Easy Typing",
"version": "5.1.10", "version": "5.3.3",
"minAppVersion": "0.15.0", "minAppVersion": "0.15.0",
"description": "Autoformat your note as typing.(Auto captalize, autospace)", "description": "Autoformat your note as typing.(Auto captalize, autospace)",
"author": "yaozhuwa", "author": "yaozhuwa",

View File

@@ -0,0 +1,16 @@
{
"pluginList": [
"Yaozhuwa/AttachFlow"
],
"pluginSubListFrozenVersion": [],
"themesList": [],
"updateAtStartup": true,
"updateThemesAtStartup": true,
"enableAfterInstall": true,
"loggingEnabled": false,
"loggingPath": "BRAT-log",
"loggingVerboseEnabled": false,
"debuggingMode": false,
"notificationsEnabled": true,
"personalAccessToken": ""
}

2419
.obsidian/plugins/obsidian42-brat/main.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
{
"id": "obsidian42-brat",
"name": "BRAT",
"version": "1.0.1",
"minAppVersion": "1.4.16",
"description": "Easily install a beta version of a plugin for testing.",
"author": "TfTHacker",
"authorUrl": "https://github.com/TfTHacker/obsidian42-brat",
"helpUrl": "https://tfthacker.com/BRAT",
"isDesktopOnly": false,
"fundingUrl": {
"Buy Me a Coffee": "https://bit.ly/o42-kofi",
"Visit my site": "https://tfthacker.com"
}
}

View File

@@ -0,0 +1,3 @@
.brat-modal .modal-button-container {
margin-top: 5px !important;
}

View File

@@ -0,0 +1 @@
data.json

335
.obsidian/plugins/remotely-save/main.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
{
"id": "remotely-save",
"name": "Remotely Save",
"version": "0.4.21",
"minAppVersion": "0.13.21",
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
"author": "fyears",
"authorUrl": "https://github.com/fyears",
"isDesktopOnly": false,
"fundingUrl": "https://github.com/remotely-save/donation"
}

View File

@@ -0,0 +1,87 @@
/* set the styles */
.password-second-confirm {
font-weight: bold;
}
.password-disclaimer {
font-weight: bold;
}
.encryptionmethod-second-confirm {
font-weight: bold;
}
.settings-auth-related {
border-top: 1px solid var(--background-modifier-border);
padding-top: 18px;
}
.s3-disclaimer {
font-weight: bold;
}
.s3-hide {
display: none;
}
.dropbox-disclaimer {
font-weight: bold;
}
.dropbox-hide {
display: none;
}
.dropbox-auth-button-hide {
display: none;
}
.dropbox-revoke-auth-button-hide {
display: none;
}
.onedrive-disclaimer {
font-weight: bold;
}
.onedrive-hide {
display: none;
}
.onedrive-auth-button-hide {
display: none;
}
.onedrive-revoke-auth-button-hide {
display: none;
}
.webdav-disclaimer {
font-weight: bold;
}
.webdav-hide {
display: none;
}
.webdis-disclaimer {
font-weight: bold;
}
.webdis-hide {
display: none;
}
.qrcode-img {
width: 350px;
height: 350px;
}
.ignorepaths-textarea {
font-family: monospace;
}
.logtohttpserver-warning {
color: red;
font-weight: bolder;
}
.setting-need-wrapping-mobile .setting-item-control {
flex-wrap: wrap;
}

View File

@@ -19,6 +19,19 @@
"source": false "source": false
} }
} }
},
{
"id": "1c8e2f0f2e175033",
"type": "leaf",
"state": {
"type": "markdown",
"state": {
"file": "并发.md",
"mode": "source",
"backlinks": true,
"source": false
}
}
} }
], ],
"stacked": true "stacked": true
@@ -71,7 +84,8 @@
} }
], ],
"direction": "horizontal", "direction": "horizontal",
"width": 300 "width": 300,
"collapsed": true
}, },
"right": { "right": {
"id": "572110f2baf458e8", "id": "572110f2baf458e8",
@@ -160,6 +174,8 @@
}, },
"left-ribbon": { "left-ribbon": {
"hiddenItems": { "hiddenItems": {
"obsidian42-brat:BRAT": false,
"remotely-save:Remotely Save": false,
"switcher:Open quick switcher": false, "switcher:Open quick switcher": false,
"graph:Open graph view": false, "graph:Open graph view": false,
"canvas:Create new canvas": false, "canvas:Create new canvas": false,
@@ -169,9 +185,16 @@
}, },
"active": "157daa1a9b93f46c", "active": "157daa1a9b93f46c",
"lastOpenFiles": [ "lastOpenFiles": [
"sql语句.md",
"代码规范/代码规范.md",
"并发.md", "并发.md",
"代码规范/代码规范.md",
"弱引用.md",
"引用类型.md",
"内存泄露.md",
"Pasted image 20240512214620.png",
"补充面试题.md",
"并发编程的其他基础知识.md",
"慢SQL优化.md",
"sql语句.md",
"OOP规约.md", "OOP规约.md",
"可读性.md", "可读性.md",
"事务使用.md", "事务使用.md",
@@ -189,14 +212,8 @@
"变量规范.md", "变量规范.md",
"常量规范.md", "常量规范.md",
"常量.md", "常量.md",
"logseq-java/pages/变量.md",
"Pasted image 20230403123034.png", "Pasted image 20230403123034.png",
"代码规范", "代码规范",
"Java 并发包中并发队列原理剖析.md",
"203-Java/203.1-Java面试/205.15-Redis/Redis.md",
"203-Java/203.1-Java面试/205.15-Redis/Redis设计与实现.md",
"Java 并发包中线程同步器原理剖析.md",
"Java 并发包中并发 List 源码剖析.md",
"203-Java/Pasted image 20230613181834.png", "203-Java/Pasted image 20230613181834.png",
"203-Java/203.1-Java面试/205.19-网络&操作系统/Pasted image 20230705222905.png", "203-Java/203.1-Java面试/205.19-网络&操作系统/Pasted image 20230705222905.png",
"203-Java/203.1-Java面试/205.19-网络&操作系统/Pasted image 20230708181100.png", "203-Java/203.1-Java面试/205.19-网络&操作系统/Pasted image 20230708181100.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

1
内存泄露.md Normal file
View File

@@ -0,0 +1 @@
不在被使用的对象,但是该对象占用的内存不能被回收

161
并发.md
View File

@@ -8,4 +8,163 @@
使用阻塞获取等待锁的方式中,必须在 try 代码块之外,并且在加锁方法与 try 代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在 finally 中无法解锁 使用阻塞获取等待锁的方式中,必须在 try 代码块之外,并且在加锁方法与 try 代码块之间没有任何可能抛出异常的方法调用,避免加锁成功后,在 finally 中无法解锁
try 中没有加锁 lock. lock ()就解锁 lock. unlock ()会抛出 IllegalMonitorStateException 异常 try 中没有加锁 lock. lock ()就解锁 lock. unlock ()会抛出 IllegalMonitorStateException 异常
try 和加锁之间有代码报错,就不会执行 finally 方法报错释放锁 try 和加锁之间有代码报错,就不会执行 finally 方法报错释放锁
分布式锁优先使用 redis 锁,而不是数据库锁 分布式锁优先使用 redis 锁,而不是数据库锁
## 线程池中提交一个任务的流程是怎样的?
使用 executor() 来提交一个工作线程submit 会放在一个 Future 里面,返回 future
提交之后就判断当前worker是都达到核心线程数最大值如果未达到就创建线程并执行任务
如果达到了核心线程最大数,就将该任务放入队列中
如果队列已满,就 addWorker 创建新线程处理任务,如果达到最大线程数,就执行拒绝策略,默认为抛出异常
## 线程池中有几种状态?分别是如何变化的?
ctl 变量AtomicInteger表示状态
RUNNING会接受新提交的任务
SHUTDOWNshutdown ()不再接受新的任务,已有任务会执行完成
STOPshutdownNow ()不接受新的任务,已有任务也会中止
先修改状态,避免新任务进来
TYDING所有线程都终止后会进入该状态等待terminated
TERMINATEDterminated ()方法执行后进入该状态
## 如何优雅的停止一个线程
开启线程execute ()无需返回值submit (),需要有返回值,通过 Future. get ()获取
Thread t1 = new Thread()
t1.stop(), 该方法会直接停止已经废弃stop 方法会释放 sync 锁ReentrantLock 不会释放
使用 interrupt 方法Thread. getCurrent. isInterrupted 可以接受到中断的信号,但是线程自己控制是否停止, 睡眠时被中断会抛出InterruptedException
## 线程池的核心线程数、最大线程数该如何设置?
CPU 密集型任务,线程计算任务多,核心线程数+1避免线程切换时间
IO 密集型任务CPU 利用率不高,线程等待时间长,核心线程数 x2避免 CPU 闲置
线程数=CPU 核心数*(1+等待时间/运行总时间)
## 如何理解 Java 并发中的可见性?
多线程修改变量时,一个线程修改了一个变量,然后其他线程可以立刻读取到这个变化的值修改时,如果在缓存就不能被其他线程读取到,使用 volatile 关键字确保读取从内存读取,写入同时写入缓存和内存
## 如何理解Java并发中的原子性
CPU 按照时间片切换,读取值后被切换,其他线程修改了,但是切换回来不会再去读取该值,而是直接去修改该值,需要通过锁机制来保证原子性
## 如何理解 Java 并发中的有序性?
![[Pasted image 20240512214620.png]]
指令重排序,正常应该先初始化再返回地址
编译器优化,修改了执行顺序
通过锁和 volatile 关键字避免
## ForkJoinPool所解决的问题是什么
RecursiveTask继承ForkJoinTask
当任务可以拆分的时候,就将任务拆分后分不同的线程处理,最后再将所有的计算结果累加
可以指定执行的线程数量,默认是机器的线程数量
## ThreadPoolExecutor的底层实现原理
addWorker 方法会新开线程
如果已经达到了最大核心线程,就会提交到队列中,有空闲的线程就会执行,队列已满会新开线程,直到最大线程数,超过队列就会拒绝新任务
## ForkJoinPool 拆分任务底层实现分析
新开一个线程会拆封任务,然后拆分两个线程 join 等待,然后继续拆分任务,直到达到最大线程数据设置
执行 compute 方法创建一个队列,把任务放进队列中,然后第一个线程取出该任务,将该大任务拆分,放入队列中,任务 1fork创建一个自己的队列将任务 1 取出来任务 2fork任务 1join任务 2join之前的线程等待的时候会取帮助其他线程的任务
JDK 19 的虚拟线程也是基于ForkJoinPool
## ForkJoinPool的底层核心原理源码解析
## JDK19中虚拟线程基于ForkJoinPool的相关实现
## 如何理解 volatile 关键字
volatile 关键字用于避免指令重排序,同时保证共享变量在内存中的可见性,底层是使用内存屏障来实现的
## CountDownLatch 和 Semaphore 的区别和底层原理
countDownLatch 为控制线程等待,让一个线程等待倒计时结束后执行,通过 countDownLatch. awit 方法阻塞,直到为 0 后继续
semaphore让线程通过 acquire 获取许可,获取不到被阻塞,通过 release 方法后返回许可
cycilcBarrier当线程达到屏障时等待一组线程
## ReentrantLock中的公平锁和非公平锁的底层实现
公平锁,去 AQS 排队获取锁
非公平锁,竞争锁,没有得到锁就去排队
这两种锁都是可重入锁,默认为非公平锁
## sleep、wait、join、yield
- 锁池
竞争锁的线程都会放入锁池中等待锁
- 等待池
调用 wait 方法会放入等待池中, 不会去竞争锁,只有 notify() 随机或 notifyAll () 会将所有线程放入锁池中
sleep 是 Thread 的静态方法wait 是 object 方法
sleep 不会释放锁,释放 CPU 执行权会冻结锁wait 会释放锁,加入到等待队列中
sleep 不依赖 synchornizedwait 依赖 synchornized
sleep 不需要被唤醒wait 需要
sleep 用于线程休眠或轮询暂停操作wait 用于线程间通信
sleep 会让出 CPU 执行时间并强制上下文切换wait 不一定wait 后可能还是会有机会竞争到锁重新执行
yield 执行后线程进入就绪状态,释放了 cpu 执行权,但是保留了执行资格,还是可能下次线程调度继续执行
join 执行后线程阻塞,直到其他线程结束或中断线程
## Sychronized的偏向锁、轻量级锁、重量级锁
首先是无锁,然后当有线程获取锁的时候,会在对象头中记录下线程的 id后面该线程来获取该锁的时候会直接获取锁当有线程竞争之后该锁升级成为轻量级锁轻量级锁为自旋锁自旋锁通过 CAS 获取预期的一个标记不会阻塞线程,当自旋过多时升级为重量级锁,重量级锁会阻塞线程
全局安全点执行清理任务的时候会尝试触发降级锁
## ThreadLocal 的底层原理
ThreadLocal 可以将数据缓存在一个线程内,每一个 Thread 对象都有一个 ThreadLocalMap这个 Map 里面 key 为对应的 ThreadLocal值为设置的缓存值读取的时候以该 ThreadLocal 为引用,在自己的 map 里找对应的 key
## ThreadLocal的原理的使用场景
数据库连接池session 会话管理
连接管理,一个线程持有一个连接,该连接对象不在线程间共享
对象跨层传输时,避免多次传递
线程间数据隔离
事务操作时,存储线程事务信息
## ThreadLocal[[内存泄露]]问题,如何避免
线程和 ThreadLocalMap 是强引用Map 和 ThreadLocal 的 Entity 也是强引用Entry 的 key 是 ThreadLocal 对象,是一个[[弱引用]],没有指向 key 的强引用该 ThreadLocal 就会被垃圾回收器回收,使用完成之后线程没有回收,但是 Entry 中的 value 是强引用不会被回收只有线程结束才会回收value 对象过多的时候就会导致内存泄漏,但是只要调用 get 或 set 方法就可以清理掉需要使用之后手动调用 remove 方法来清除该值
## 阿里一面:如何查看线程死锁
## 阿里一面:线程之间如何进行通讯的
## 并发、并行、串行
## 并发篇1
## 并发篇2-1
## 并发篇2-2
## 并发篇3
## 并发4
## 并发5
## 并发三大特性
## 对线程安全的理解
## 京东一面Java死锁如何避免
## 京东一面:如果你提交任务时,线程池队列已满,这时会发生什么
## 蚂蚁一面sychronized的自旋锁、偏向锁、轻量级锁、重量级锁分别介绍和联系
## 说说你对守护线程的理解
## 为什么使用线程池,参数解释
## 线程的生命周期及状态
## 线程池线程复用的原理
## 线程池的底层工作原理

View File

@@ -0,0 +1 @@
一般用于缓存类的数据

160
慢SQL优化.md Normal file
View File

@@ -0,0 +1,160 @@
## 优化方式
数据量
- SQL 执行后返回给客户端的数据量的大小
- 数据量越大需要扫描的 I/O 次数越多,数据库服务器的 IO 瓶颈
取数据的方式
- 数据在缓存还是磁盘
- 能否通过全局索引快速寻址
- 是否结合谓词条件命中全局索引加速扫描
数据加工的方式
- 排序、子查询、聚合、关联等需要将数据取到临时表中,再对数据加工
- 对于数据量多的计算,会消耗大量 CPU 资源
- 是否选择了合适的 join 方式
## 优化思路
减少数据扫描(磁盘访问)
- 尽量在查询中加入一些可以提前过滤数据的位于条件,减少数据扫描量,对查询更加友好
- 扫描大表数据时是否可以命中索引,减少回表,避免全表扫描
返回更少数据(减少网络传输或磁盘访问)
减少交互次数(减少网络传输)
- 将数据存放在更快的地方
- 某条查询涉及大表,无法进一步优化,如果返回数据量不大但访问频率很高,可以将返回的数据放在应用端缓存或 redis 缓存中,提高存取速度
减少服务器开销CPU 和内存)
避免大事务
利用更多资源
## 优化案例
- 数据分页优化
```sql
select * from table_name where type = ? limit ?,?;
```
偏移 id
```sql
lastId = 0 or min(id)
do {
select * from table_name where type = ? and id > {#lastId} limit ?;
lastId = max(id)
} while (isNotEmpty)
```
分段查询
优点:可并行查询,分段互不依赖
缺点:依赖连续性,数据过于分散代价较高
```sql
minId = min(id) maxId = max(id)
for(int i = minId; i <= maxId; i+=pageSize){
select * from table_name where type = ? and id between i and i+ pageSize;
}
```
- 优化 groupBy
将不需要的数据在 groupBy 之前过滤掉
```sql
select job, avg(sal) from table_name group by job having job = 'manager'
```
```sql
select job, avg(sal) from table_name where job = 'manager' group by job
```
- 范围查询
联合索引中如果某个列存在范围查询(大于小于),其右边的列是否还有意义
设计时需要结合业务需求
- 优化 order by
索引
```sql
KEY `idx_account_trade_date_time` (`account_number`,`trade_date_time`)
KEY `idx_trade_date_time` (`trade_date_time`)
KEY `idx_create_time` (`create_time`)
```
慢 SQL
```sql
select id,,,creator,modifier,create_time,update_time from satatement where (account_number = 'XXX' and create_time > '2024-04-24 00:00:00' and create_time < '2024-04-25 00:00:00' and dc_flag = 'C') order by trade_date_time desc, id desc limit 0,1000;
```
```sql
select id,,,creator,modifier,create_time,update_time from satatement where (account_number = 'XXX' and create_time > '2024-04-24 00:00:00' and create_time < '2024-04-25 00:00:00' and dc_flag = 'C') order by create_time desc, id desc limit 0,1000;
```
MySQL 使不使用索引与所查列无关只与索引本身where 条件order by group by 字段有关,索引的作用为查找和排序
- 业务拆分
```sql
select * from order where status = 'S' and update_time < now-5min limit 500
```
业务数据增长status 无法走索引,结合业务特性,对数据获取按日期拆分
```sql
date = now; minDate = now - 10 day
while(date > minDate) {
select * from order where order_date = #{date} and status = 'S' and update_time < now-5min limit 500
date = date + 1
}
```
## 数据库结构优化
- 范式优化表的设计合理化3 NF消除冗余节省空间
- 反范式优化:适当添加冗余(减少 join
- 拆分表:分区将数据在物理上分隔开,不同分区数据表存储于不同磁盘中,查询时只需到表分区中扫描,无需全表扫描,同时分散了磁盘 IO
## SQL 语句优化
1. 避免子查询
2. 用 in 替换 or
3. 读取适当的记录 limit MN不要读取多余的记录
4. 禁止不必要的 order by 排序
5. 总和查询禁止排重用 union all
6. 避免随机取数据
7. 将多次插入换成批量插入
8. 只返回必要的列select 具体字段
9. 区分 in 和 exist
10. 优化 group by
11. 尽量使用数字型字段
12. 优化 join 语句
## 大表优化
- 分库分表
- 读写分离
- 数据定期归档
## 索引的优缺点
优点
- 提高查询语句执行效率,减少 IO 操作次数
- 创建唯一性索引,保证数据库中每一行数据的唯一性
- 加索引的列会进行排序,使用分组和排序子句可以减少时间
缺点
- 索引需要占用一定空间
- 创建索引和维护索引需要时间
- 对表中数据进行修改时,索引也要动态维护,降低了更新效率
## 索引结构
## 数据行格式
MySQL 有 4 种存储格式:
1. Compact
2. Redundant5.0 版本前,已废弃)
3. DynamicMySQL 5.7 默认格式)
4. Compressed
Dynamic 下,对于处理行溢出,仅存放溢出页内存地址
## 索引设计原则
哪些情况适合建索引
- 数据有唯一性限制
- 频繁 where 条件
- 进场 group by 和 order by 字段,都有时建议联合索引
- 经常 distinct 字段
- 多表连接时的字段
- 数量最好不要超过 3 张
- 多表查询时 where 条件建索引
- 对连接字段建索引,且数据类型保持一致
- 确定数据范围情况下使用数据类型较小的字段,索引也会占空间
- 字符串建索引使用前缀
- 节省空间
- 可定位到相同前缀,然后通过主键查询完整字符串
- 区分度高的字段(散列性高)的字段
- 多个字段需要建索引,联合索引优于单值索引
不需要索引
- where 条件中用不到
- 数据量小,小于 1000 条
- 大量重复数据的列
- 避免在经常更新的表或字段
- 不建议主键使用无序的值
- 不定义冗余或重复索引
- 已有联合索引不要单独再建单索引
## 索引优化之 MRR
## 索引下推
idx (name, age)
```sql
select * from tuser where name like '张%' and age=10;
```
直接在联合索引里面过滤过滤两次完后在回表
条件
- 只能用于 range、ref、eq_ref、ref_or_null 访问方法
- 只使用 InnoDB 和 MyISAM
- 对存储引擎来说,只适用于二级索引(辅助索引)
- 引用了子查询的条件不能下推
- 引用了存储函数的条件不能下推,存储引擎无法调用存储函数