Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,395 changes: 5 additions & 1,390 deletions docs/java/basis/Java基础知识.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions docs/java/jvm/Java内存区域.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ JDK 1.8 的时候,方法区(HotSpot 的永久代)被彻底移除了(JDK1

#### 2.5.3 为什么要将永久代 (PermGen) 替换为元空间 (MetaSpace) 呢?

1. 整个永久代有一个 JVM 本身设置固定大小上限,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。
>当你元空间溢出时会得到如下错误: `java.lang.OutOfMemoryError: MetaSpace`
1. 整个永久代有一个 JVM 本身设置的固定大小上限,无法进行调整,而元空间使用的是直接内存,受本机可用内存的限制,虽然元空间仍旧可能溢出,但是比原来出现的几率会更小。
>当元空间溢出时会得到如下错误: `java.lang.OutOfMemoryError: MetaSpace`

你可以使用 `-XX:MaxMetaspaceSize` 标志设置最大元空间大小,默认值为 unlimited,这意味着它只受系统内存的限制。`-XX:MetaspaceSize` 调整标志定义元空间的初始大小如果未指定此标志,则 Metaspace 将根据运行时的应用程序需求动态地重新调整大小。

Expand Down
6 changes: 4 additions & 2 deletions docs/java/jvm/类加载过程.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚

### 初始化

初始化是类加载的最后一步,也是真正执行类中定义的 Java 程序代码(字节码),初始化阶段是执行初始化方法 `<clinit> ()`方法的过程。
初始化阶段是执行初始化方法 `<clinit> ()`方法的过程,是类加载的最后一步,这一步 JVM 才开始真正执行类中定义的 Java 程序代码(字节码)

对于`<clinit> ()` 方法的调用,虚拟机会自己确保其在多线程环境中的安全性。因为 `<clinit> ()` 方法是带锁线程安全,所以在多线程环境下进行类初始化的话可能会引起死锁,并且这种死锁很难被发现。
> 说明: `<clinit> ()`方法是编译之后自动生成的。

对于`<clinit> ()` 方法的调用,虚拟机会自己确保其在多线程环境中的安全性。因为 `<clinit> ()` 方法是带锁线程安全,所以在多线程环境下进行类初始化的话可能会引起多个进程阻塞,并且这种阻塞很难被发现。

对于初始化阶段,虚拟机严格规范了有且只有5种情况下,必须对类进行初始化(只有主动去使用类才会初始化类):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,7 @@ protected final boolean compareAndSetState(int expect, int update) {
- **Exclusive**(独占):只有一个线程能执行,如 `ReentrantLock`。又可分为公平锁和非公平锁:
- 公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
- 非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
- **Share**(共享):多个线程可同时执行,如` CountDownLatch`、`Semaphore`、`CountDownLatch`、 `CyclicBarrier`、`ReadWriteLock` 我们都会在后面讲到。
- **Share**(共享):多个线程可同时执行,如` CountDownLatch`、`Semaphore`、 `CyclicBarrier`、`ReadWriteLock` 我们都会在后面讲到。

`ReentrantReadWriteLock` 可以看成是组合式,因为 `ReentrantReadWriteLock` 也就是读写锁允许多个线程同时对某一资源进行读。

Expand Down
78 changes: 39 additions & 39 deletions docs/java/multi-thread/AQS原理以及AQS同步组件总结.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions docs/java/new-features/Java8新特性总结.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "b"

`java.util.Stream` 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如` java.util.Collection` 的子类,List 或者 Set, Map 不支持。Stream 的操作可以串行执行或者并行执行。

首先看看Stream是怎么用,首先创建实例代码的用到的数据List
首先看看Stream是怎么用,首先创建实例代码需要用到的数据List

```java
List<String> stringList = new ArrayList<>();
Expand Down Expand Up @@ -552,7 +552,7 @@ Stream提供了多种匹配操作,允许检测指定的Predicate是否匹配

### Reduce(规约)

这是一个 **最终操作** ,允许通过指定的函数来讲stream中的多个元素规约为一个元素,规约后的结果是通过Optional 接口表示的:
这是一个 **最终操作** ,允许通过指定的函数来将stream中的多个元素规约为一个元素,规约后的结果是通过Optional 接口表示的:

```java
//测试 Reduce (规约)操作
Expand Down Expand Up @@ -705,7 +705,7 @@ map.merge(9, "concat", (value, newValue) -> value.concat(newValue));
map.get(9); // val9concat
```

Merge 做的事情是如果键名不存在则插入,否则则对原键对应的值做合并操作并重新插入到map中
Merge 做的事情是如果键名不存在则插入,否则对原键对应的值做合并操作并重新插入到map中

## Date API(日期相关API)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<!-- TOC -->

- [一文搞懂 RabbitMQ 的重要概念以及安装](#一文搞懂-rabbitmq-的重要概念以及安装)
- [一 RabbitMQ 介绍](#一-rabbitmq-介绍)
- [1.1 RabbitMQ 简介](#11-rabbitmq-简介)
- [1.2 RabbitMQ 核心概念](#12-rabbitmq-核心概念)
- [1.2.1 Producer(生产者) 和 Consumer(消费者)](#121-producer生产者-和-consumer消费者)
- [1.2.2 Exchange(交换器)](#122-exchange交换器)
- [1.2.3 Queue(消息队列)](#123-queue消息队列)
- [1.2.4 Broker(消息中间件的服务节点)](#124-broker消息中间件的服务节点)
- [1.2.5 Exchange Types(交换器类型)](#125-exchange-types交换器类型)
- [① fanout](#-fanout)
- [② direct](#-direct)
- [③ topic](#-topic)
- [④ headers(不推荐)](#-headers不推荐)
- [二 安装 RabbitMq](#二-安装-rabbitmq)
- [2.1 安装 erlang](#21-安装-erlang)
- [2.2 安装 RabbitMQ](#22-安装-rabbitmq)
- [一 RabbitMQ 介绍](#一-rabbitmq-介绍)
- [1.1 RabbitMQ 简介](#11-rabbitmq-简介)
- [1.2 RabbitMQ 核心概念](#12-rabbitmq-核心概念)
- [1.2.1 Producer(生产者) 和 Consumer(消费者)](#121-producer生产者-和-consumer消费者)
- [1.2.2 Exchange(交换器)](#122-exchange交换器)
- [1.2.3 Queue(消息队列)](#123-queue消息队列)
- [1.2.4 Broker(消息中间件的服务节点)](#124-broker消息中间件的服务节点)
- [1.2.5 Exchange Types(交换器类型)](#125-exchange-types交换器类型)
- [① fanout](#-fanout)
- [② direct](#-direct)
- [③ topic](#-topic)
- [④ headers(不推荐)](#-headers不推荐)
- [二 安装 RabbitMq](#二-安装-rabbitmq)
- [2.1 安装 erlang](#21-安装-erlang)
- [2.2 安装 RabbitMQ](#22-安装-rabbitmq)

<!-- /TOC -->

Expand Down Expand Up @@ -123,7 +123,7 @@ direct 类型常用在处理有优先级的任务,根据任务的优先级把

- RoutingKey 为一个点号“.”分隔的字符串(被点号“.”分隔开的每一段独立的字符串称为一个单词),如 “com.rabbitmq.client”、“java.util.concurrent”、“com.hidden.client”;
- BindingKey 和 RoutingKey 一样也是点号“.”分隔的字符串;
- BindingKey 中可以存在两种特殊字符串“*”和“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)。
- BindingKey 中可以存在两种特殊字符串“\*”和“#”,用于做模糊匹配,其中“\*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)。

![topic 类型交换器](http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-12-16/73843.jpg)

Expand Down
75 changes: 75 additions & 0 deletions docs/system-design/framework/mybatis/mybatis-interview.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,81 @@ public interface StuMapper {

Dao 接口的工作原理是 JDK 动态代理,MyBatis 运行时会使用 JDK 动态代理为 Dao 接口生成代理 proxy 对象,代理对象 proxy 会拦截接口方法,转而执行`MappedStatement`所代表的 sql,然后将 sql 执行结果返回。

##### ==补充:==

Dao接口方法可以重载,但是需要满足以下条件:

1. 仅有一个无参方法和一个有参方法
2. 多个有参方法时,参数数量必须一致。且使用相同的 `@Param` ,或者使用 `param1` 这种

测试如下:

`PersonDao.java`

```java
Person queryById();

Person queryById(@Param("id") Long id);

Person queryById(@Param("id") Long id, @Param("name") String name);
```

`PersonMapper.xml`

```xml
<select id="queryById" resultMap="PersonMap">
select
id, name, age, address
from person
<where>
<if test="id != null">
id = #{id}
</if>
<if test="name != null and name != ''">
name = #{name}
</if>
</where>
limit 1
</select>
```

`org.apache.ibatis.scripting.xmltags.DynamicContext.ContextAccessor#getProperty`方法用于获取`<if>`标签中的条件值

```java
public Object getProperty(Map context, Object target, Object name) {
Map map = (Map) target;

Object result = map.get(name);
if (map.containsKey(name) || result != null) {
return result;
}

Object parameterObject = map.get(PARAMETER_OBJECT_KEY);
if (parameterObject instanceof Map) {
return ((Map)parameterObject).get(name);
}

return null;
}
```

`parameterObject`为map,存放的是Dao接口中参数相关信息。

`((Map)parameterObject).get(name)`方法如下

```java
public V get(Object key) {
if (!super.containsKey(key)) {
throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + keySet());
}
return super.get(key);
}
```

1. `queryById()`方法执行时,`parameterObject`为null,`getProperty`方法返回null值,`<if>`标签获取的所有条件值都为null,所有条件不成立,动态sql可以正常执行。
2. `queryById(1L)`方法执行时,`parameterObject`为map,包含了`id`和`param1`两个key值。当获取`<if>`标签中`name`的属性值时,进入`((Map)parameterObject).get(name)`方法中,map中key不包含`name`,所以抛出异常。
3. `queryById(1L,"1")`方法执行时,`parameterObject`中包含`id`,`param1`,`name`,`param2`四个key值,`id`和`name`属性都可以获取到,动态sql正常执行。

#### 4、MyBatis 是如何进行分页的?分页插件的原理是什么?

注:我出的。
Expand Down