mirror of
https://github.com/Snailclimb/JavaGuide
synced 2025-06-20 22:17:09 +08:00
Merge pull request #2042 from paigeman/paigeman-patch-2
chore: fix typos
This commit is contained in:
commit
61ab3dc5a7
@ -552,7 +552,7 @@ public class MyServiceLoader<S> {
|
|||||||
|
|
||||||
其实不难发现,SPI 机制的具体实现本质上还是通过反射完成的。即:**我们按照规定将要暴露对外使用的具体实现类在 `META-INF/services/` 文件下声明。**
|
其实不难发现,SPI 机制的具体实现本质上还是通过反射完成的。即:**我们按照规定将要暴露对外使用的具体实现类在 `META-INF/services/` 文件下声明。**
|
||||||
|
|
||||||
另外,SPI 机制在很多框架中都有应用:Spring 框架的基本原理也是类似的反射。还有 Dubbo 框架提供同样的 SPI 扩展机制,只不过 Dubbo 和 spring 框架中的 SPI 机制具体实现方式跟咱们今天学得这个有些细微的区别,不过整体的原理都是一致的,相信大家通过对 JDK 中 SPI 机制的学习,能够一通百通,加深对其他高深框的理解。
|
另外,SPI 机制在很多框架中都有应用:Spring 框架的基本原理也是类似的方式。还有 Dubbo 框架提供同样的 SPI 扩展机制,只不过 Dubbo 和 spring 框架中的 SPI 机制具体实现方式跟咱们今天学得这个有些细微的区别,不过整体的原理都是一致的,相信大家通过对 JDK 中 SPI 机制的学习,能够一通百通,加深对其他高深框的理解。
|
||||||
|
|
||||||
通过 SPI 机制能够大大地提高接口设计的灵活性,但是 SPI 机制也存在一些缺点,比如:
|
通过 SPI 机制能够大大地提高接口设计的灵活性,但是 SPI 机制也存在一些缺点,比如:
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ public interface RandomAccess {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`ArrayList` 实现了 `RandomAccess` 接口, 而 `LinkedList` 没有实现。为什么呢?我觉得还是和底层数据结构有关!`ArrayList` 底层是数组,而 `LinkedList` 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问。,`ArrayList` 实现了 `RandomAccess` 接口,就表明了他具有快速随机访问功能。 `RandomAccess` 接口只是标识,并不是说 `ArrayList` 实现 `RandomAccess` 接口才具有快速随机访问功能的!
|
`ArrayList` 实现了 `RandomAccess` 接口, 而 `LinkedList` 没有实现。为什么呢?我觉得还是和底层数据结构有关!`ArrayList` 底层是数组,而 `LinkedList` 底层是链表。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问。`ArrayList` 实现了 `RandomAccess` 接口,就表明了他具有快速随机访问功能。 `RandomAccess` 接口只是标识,并不是说 `ArrayList` 实现 `RandomAccess` 接口才具有快速随机访问功能的!
|
||||||
|
|
||||||
### 说一说 ArrayList 的扩容机制吧
|
### 说一说 ArrayList 的扩容机制吧
|
||||||
|
|
||||||
|
@ -515,7 +515,7 @@ JDK 提供的所有现成的 `Lock` 实现类,包括 `synchronized` 关键字
|
|||||||
在下面的代码中,`method1()` 和 `method2()`都被 `synchronized` 关键字修饰,`method1()`调用了`method2()`。
|
在下面的代码中,`method1()` 和 `method2()`都被 `synchronized` 关键字修饰,`method1()`调用了`method2()`。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class ReentrantLockDemo {
|
public class SynchronizedDemo {
|
||||||
public synchronized void method1() {
|
public synchronized void method1() {
|
||||||
System.out.println("方法1");
|
System.out.println("方法1");
|
||||||
method2();
|
method2();
|
||||||
|
@ -214,7 +214,7 @@ static class Entry extends WeakReference<ThreadLocal<?>> {
|
|||||||
- **`FixedThreadPool`**:该方法返回一个固定线程数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。
|
- **`FixedThreadPool`**:该方法返回一个固定线程数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。
|
||||||
- **`SingleThreadExecutor`:** 该方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。
|
- **`SingleThreadExecutor`:** 该方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。
|
||||||
- **`CachedThreadPool`:** 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。
|
- **`CachedThreadPool`:** 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。
|
||||||
- **`ScheduledThreadPool`**:该返回一个用来在给定的延迟后运行任务或者定期执行任务的线程池。
|
- **`ScheduledThreadPool`**:该方法返回一个用来在给定的延迟后运行任务或者定期执行任务的线程池。
|
||||||
|
|
||||||
对应 `Executors` 工具类中的方法如图所示:
|
对应 `Executors` 工具类中的方法如图所示:
|
||||||
|
|
||||||
@ -373,10 +373,10 @@ public static class CallerRunsPolicy implements RejectedExecutionHandler {
|
|||||||
ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
ThreadFactory threadFactory = new ThreadFactoryBuilder()
|
||||||
.setNameFormat(threadNamePrefix + "-%d")
|
.setNameFormat(threadNamePrefix + "-%d")
|
||||||
.setDaemon(true).build();
|
.setDaemon(true).build();
|
||||||
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory)
|
ExecutorService threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.MINUTES, workQueue, threadFactory);
|
||||||
```
|
```
|
||||||
|
|
||||||
**2、自己实现 `ThreadFactor`。**
|
**2、自己实现 `ThreadFactory`。**
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
@ -205,7 +205,7 @@ CPU 密集型简单理解就是利用 CPU 计算能力的任务比如你在内
|
|||||||
线程池提供了两个关闭方法:
|
线程池提供了两个关闭方法:
|
||||||
|
|
||||||
- **`shutdown()`** :关闭线程池,线程池的状态变为 `SHUTDOWN`。线程池不再接受新任务了,但是队列里的任务得执行完毕。
|
- **`shutdown()`** :关闭线程池,线程池的状态变为 `SHUTDOWN`。线程池不再接受新任务了,但是队列里的任务得执行完毕。
|
||||||
- **`shutdownNow()`** :关闭线程池,线程的状态变为 `STOP`。线程池会终止当前正在运行的任务,并停止处理排队的任务并返回正在等待执行的 List。
|
- **`shutdownNow()`** :关闭线程池,线程池的状态变为 `STOP`。线程池会终止当前正在运行的任务,停止处理排队的任务并返回正在等待执行的 List。
|
||||||
|
|
||||||
调用完 `shutdownNow` 和 `shuwdown` 方法后,并不代表线程池已经完成关闭操作,它只是异步的通知线程池进行关闭处理。如果要同步等待线程池彻底关闭后才继续往下执行,需要调用`awaitTermination`方法进行同步等待。
|
调用完 `shutdownNow` 和 `shuwdown` 方法后,并不代表线程池已经完成关闭操作,它只是异步的通知线程池进行关闭处理。如果要同步等待线程池彻底关闭后才继续往下执行,需要调用`awaitTermination`方法进行同步等待。
|
||||||
|
|
||||||
|
@ -611,7 +611,7 @@ Exception in thread "main" java.util.concurrent.TimeoutException
|
|||||||
#### `shutdown()`VS`shutdownNow()`
|
#### `shutdown()`VS`shutdownNow()`
|
||||||
|
|
||||||
- **`shutdown()`** :关闭线程池,线程池的状态变为 `SHUTDOWN`。线程池不再接受新任务了,但是队列里的任务得执行完毕。
|
- **`shutdown()`** :关闭线程池,线程池的状态变为 `SHUTDOWN`。线程池不再接受新任务了,但是队列里的任务得执行完毕。
|
||||||
- **`shutdownNow()`** :关闭线程池,线程的状态变为 `STOP`。线程池会终止当前正在运行的任务,并停止处理排队的任务并返回正在等待执行的 List。
|
- **`shutdownNow()`** :关闭线程池,线程池的状态变为 `STOP`。线程池会终止当前正在运行的任务,并停止处理排队的任务并返回正在等待执行的 List。
|
||||||
|
|
||||||
#### `isTerminated()` VS `isShutdown()`
|
#### `isTerminated()` VS `isShutdown()`
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user