Seven's blog

你不会找到路,除非你敢于迷路

0%

ARTS-13

Algorithm

1313. 解压缩编码列表

解法一:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int[] decompressRLElist(int[] nums) {
int resultLength = 0;
int loop = nums.length / 2;
// 计算目标数组的长度
for (int i = 0; i < loop; i++) {
resultLength += nums[2 * i];
}
// 执行解码操作
int[] result = new int[resultLength];
int resultIndex = 0;
for (int i = 0; i < loop; i++) {
for (int j = 0; j < nums[2 * i]; j++) {
result[resultIndex] = nums[2 * i + 1];
resultIndex++;
}
}
return result;
}
}

执行用时:1ms,内存消耗:37.8MB。

解法二:

优化了一下循环策略,性能差别不大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int[] decompressRLElist(int[] nums) {
int resultLength = 0;
for (int i = 0; i < nums.length; i += 2) {
resultLength += nums[i];
}
int[] result = new int[resultLength];
int resultIndex = 0;
for (int i = 0; i < nums.length; i += 2) {
for (int j = 0; j < nums[i]; j++) {
result[resultIndex] = nums[i + 1];
resultIndex++;
}
}
return result;
}
}

执行用时:1ms,内存消耗:37.3MB。

Review

7 Skills of Highly Effective Programmers

  1. 学习如何阅读他人的代码
  2. 对坏项目的意识
  3. 避免无效开会
  4. 学透你的版本控制系统
  5. 编写简单可维护的代码
  6. 学会排列优先级和说“不”
  7. 学习设计思想

Tip

MySQL 中的锁

根据加锁的范围, MySQL 里面的锁大致可以分成全局锁, 表级锁和行锁三类.

全局锁

顾名思义, 全局锁就是对整个数据库实例加锁. MySQL 提供了一个加全局读锁的方法, 命令是 Flush tables with read lock(FLWRL). 当你需要让整个库处于只读状态的时候, 可以使用这个命令, 之后其他线程的以下语句会被阻塞: 数据更新语句 (数据的增删查改), 数据定义语句 (包括建表, 修改表结构) 和更新类事务的提交语句.

表级锁

MySQL 里面表级别的锁有两种: 一种是表锁, 一种是元数据锁 (meta data lock, MDL).

表锁

表锁的语法是 lock tables ... read / write. 与 FTWRL, 可以用 unlock tables 主动释放锁, 也可以在客户端断开的时候自动释放.

metadata lock (MDL)

MDL 不需要显式使用, 在访问一个表的时候会被自动加上. MDL 的作用是保证读写的正确性.

行锁

行锁就是针对数据表中 “行记录” 的锁. 也就是说, 两个针对同一行的更新操作不能同时执行, 后提交的事务必须在先提交的事务执行完毕之后才能执行.

两阶段锁

在 InnoDB 事务中, 行锁是在需要的时候加上的, 但并不是不需要了就立刻释放, 而是要等到事务结束时才释放. 这个就是两阶段锁协议.

所以, 如果你的食物中需要锁多个行, 要把最可能造成锁冲突, 最可能影响并发度的锁尽量往后放.

死锁和死锁检测

当并发系统中不同线程出现循环资源依赖, 涉及的线程都在等别的线程释放资源是, 就会导致这几个线程都进入无期限等待的状态, 称为死锁.

解决方案:

  • 直接进入等待, 直到超时. 这个超时时间可以通过参数 innodb_lock_wait_timeout 来设置.

    但是这种方法可能会出现误伤, 比如杀掉正处于锁等待阶段的线程.

  • 发起死锁检测, 发现死锁后, 主动回滚死锁链条中的某一个事务, 让其他事物得以继续执行.

    但是这种方法有额外的负担.

对于热点行更新导致的性能问题:

  • 一种头痛医头的解决方案, 就是如果你能确保这个业务一定不会出现死锁, 可以临时把死锁检测关掉.

    但是这种方法可能有损业务.

  • 另一个思路是控制并发度, 并发控制最好做在服务端.

Share

回首 2019,似乎一直在忙碌,但始终感觉寸步未进。静心回想,大概是因为贪吧。

想学 Java,想学 MySQL,想学 Docker,想学运维,想学产品,想学设计,想学 Vue,想学 React,想学写作,想学书法,想学理财…… 想学的东西太多,做得事情太杂,始终没有主线。多线程切换,全部都是蜻蜓点水,未曾深入。什么都想要,到最后什么都得不到。

老早就知道我的目标应该是成为一个 “T 型人”,一专多能。老早就知道我应该缩小行动半径,先纵向深入研究自己的专业领域。但是走到行动阶段,又总是被路途中的风景所吸引,从而迷失方向。

之前总是安慰自己说日进一步,只要自己始终在前进,终有一天能够达成目标。可是如果没有方向指引,连目标是什么都摇摆不定,所谓的日进一步也不过是在小小的庭院里转圈圈罢了。

2020,终究还是要作一下规划的。确保自己先精通本行,然后再逐步向周边延伸。一次只做一件事,一次做好一件事。

嗯,加油!

微信公众号
扫码关注, 一起进步!