0 启动流程

  1. 解析启动参数,打印 logo。
  2. 通过工厂对配置进行判断获取相应的应用服务器(默认 undertow)。
  3. 判断是否是开发模式(默认),如果是则定期对文件进行扫描(3 * 1010)。
  4. 回调各个 listener 的 onJbootStarted() 方法。

1 如何使用 main 文件启动一个应用服务器?

阅读全文 »

除非你觉得你的时间不是很宝贵,否则不要看这篇流水账式的博文,这只是篇个人的工作的学习一个总结而已,没有包含任何的技术细节
阅读全文 »

在复习阻塞队列时,使用原生的 wait、notify 自己实现的阻塞队列竟然出现超最大长度的问题,有问题的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public class SimulateBlockingQueue {

// 底层队列
private LinkedList list = new LinkedList();

// 队列数据的上下限
private final int minSize = 0;
private final int maxSize;

public SimulateBlockingQueue(int size) {
this.maxSize = size - 1;
}

private Object lock = new Object();

/**
* 存数据
* @param obj
*/
public void put(Object obj) {
synchronized (lock) {
while (list.size() == this.maxSize) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.add(obj);
lock.notify();
}
}

/**
* 取数据
* @return
*/
public Object get() {
Object result = null;
synchronized (lock) {
while (list.size() == this.minSize) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result = list.removeFirst();
lock.notify();
}
return result;
}

public int getSize() {
return list.size();
}

public static void main(String[] args) throws InterruptedException {
final SimulateBlockingQueue mq = new SimulateBlockingQueue(5);

Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
mq.put(i);
System.out.println("++增加:" + i);
}
}
}, "t1");
t1.start();

Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("移除:" + mq.get());
}
}
}, "t2");
t2.start();

TimeUnit.SECONDS.sleep(2);
}

}
阅读全文 »

索引能够轻易将查询性能提高几个数量级,“最优”的索引有时比一个“好的”索引性能要好两个数量级。创建一个真正“最优”的索引经常需要重写查询。

1 索引基础

1.1 索引的类型

在 MySQL 中,索引是在存储引擎层而不是服务器层实现的。所以,并没有统一的索引标准。即使多个存储引擎支持同一种类型的索引,其底层的事先也可能不同。

阅读全文 »

1 选择优化的数据类型

  1. 更小的通常更好
  2. 简单就好:整型比字符操作代价更低,使用 MySQL 内建的类型而不是字符串来存储日期和时间,以及使用整型存储 IP 地址
  3. 尽量避免 NULL:可为 NULL 的列会使用更多的存储空间。 InnoDB 使用单独的位(bit)存储 NULL 值,但这不适用于 MyISAM
阅读全文 »

在《架构探险——从零开始架构》中,第四章的自己实现 ThreadLocal 感悟:
ThreadLocal 中虽然使用了 Map 进行保存线程变量,但是为了防止引入锁(Map 的多线程访问)影响性能,从而使用让不同的 Thread 保存不同的 Map(ThreadLoaclMap)实例,这样不同的Thread 有不同的 ThreadLocalMap 实例,就不用考虑锁的问题。
另外为了避免内存泄漏、回收不及时等问题,从而让 ThreadLocalMap 的 key 使用弱引用。
同时,为了保证当 key 为 null 时,value 无法正常释放时,在每次 set 时,都会遍历 key ,当 key 为 null 则会执行 replaceStaleEntry(),即将 key 为 null 的 value 值也置为 null,从而来让其回收。
这里讲解更加详细:http://www.jasongj.com/java/threadlocal/
这是原理:

笔记总结+源码:https://github.com/LiWenGu/MySourceCode/tree/master/mybatis0to1
在前七章都打了对应的标签,可以通过 git checkout来。

总结就是,将 sql 语句从代码中抽离出来,通过 xml 的配置来实现单表、多表的映射,最后通过动态代理来执行方法,很强的解耦性。
把 SQL 放在了 XML 中,然后用一些判断来实现动态 SQL ,最后通过 SqlSession 、SqlSessionFacotry 的生命周期来绑定一级、二级缓存。
不学之前感觉很神奇,学完之后也就那么回事,不过还是要多学学基础,例如读取配置、缓存、一级动态代理等。

Please look after this bear, thank you.

联想最近的北京大兴事件,有点苦涩,现代人的城市,忘记如何对待一个流浪的人。

每个城市都会有着提着行李箱,下着雨,在站台上的外乡人,唯一的区别是如何对待他们。


城市应该有它自己的包容心。

1 本章概要

本章中,将以密码软件 PGP(Pretty Good Privacy)为题材,思考一下将前面章节中学习的密码技术进行组合的方法。

2 PGP简介

PGP 是 1990 年编写的密码软件。

2.1 PGP 的功能

1.对称密码

2.公钥密码

3.数字签名

4.单向散列函数

5.证书

6.压缩

7.文本数据

8.大文件的拆分和平和

阅读全文 »

1 骡子的锁匠铺

很久很久之前,骡子开了一家锁匠铺,他说:“我做的锁头很坚固,小偷绝对打不开。”因此动物村里所有的动物都为自己的房子装上了骡子做的锁。
骡子做的锁确实很坚固,但是每把锁头上用的钥匙居然都是同一个形状的。因此小偷只要得到了一栋房子的钥匙,就可以打开所有房子的锁了。
教训:坚固的锁头固然重要,但不可预测的钥匙更加重要。

阅读全文 »