1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-16 18:10:13 +08:00

Compare commits

...

9 Commits

Author SHA1 Message Date
Guide
6915d159ff
Merge pull request #2615 from MonsterFanSec/main
Update io-basis.md
2025-02-23 21:44:43 +08:00
Guide
0f0f46cc50
Merge pull request #2618 from imba-tjd/patch-1
fix md style
2025-02-23 21:44:18 +08:00
Guide
d48f11c171
Merge pull request #2617 from flying-pig-z/patch-2
删除RocketMQ文章中的多余字符
2025-02-23 21:44:00 +08:00
谭九鼎
1b701c44d2
fix md style 2025-02-23 20:56:18 +08:00
flying pig
90dc871ea8
删除RocketMQ文章中的多余字符 2025-02-23 16:49:11 +08:00
Guide
ffcccdca0d [dcos update]修正线程池内容部分描述 2025-02-22 15:35:59 +08:00
Guide
e26afb3739
Merge pull request #2616 from wayne-pq/feature_add_future
add: 增加 Future 的源码参考文章
2025-02-22 15:33:10 +08:00
wayne
18ea39f934 add: 增加 Future 的源码参考文章 2025-02-22 14:42:44 +08:00
MonsterFan
34eb4d644a
Update io-basis.md
笔误 - Java IO 基础知识总结 - BufferedOutputStream(字节缓冲输出流)
BufferedOutputStream(字节缓冲输出流)这部分的描述,最后是“提高了读取效率”,这里应该是提高输出或者写出的效率吧?
解决方案:删除了“读取”
2025-02-21 14:59:16 +08:00
9 changed files with 28 additions and 28 deletions

View File

@ -326,9 +326,9 @@ myStack.pop();//报错java.lang.IllegalArgumentException: Stack is empty.
当我们需要按照一定顺序来处理数据的时候可以考虑使用队列这个数据结构。
- **阻塞队列:** 阻塞队列可以看成在队列基础上加了阻塞操作的队列。当队列为空的时候,出队操作阻塞,当队列满的时候,入队操作阻塞。使用阻塞队列我们可以很容易实现“生产者 - 消费者“模型。
- **线程池中的请求/任务队列:** 线程池中没有空闲线程时,新的任务请求线程资源时,线程池该如何处理呢?答案是将这些请求放在队列中,当有空闲线程的时候,会循环中反复从队列中获取任务来执行。队列分为无界队列(基于链表)和有界队列(基于数组)。无界队列的特点就是可以一直入列,除非系统资源耗尽,比如:`FixedThreadPool` 使用无界队列 `LinkedBlockingQueue`。但是有界队列就不一样了,当队列满的话后面再有任务/请求就会拒绝,在 Java 中的体现就是会抛出`java.util.concurrent.RejectedExecutionException` 异常。
- 栈:双端队列天生便可以实现栈的全部功能(`push``pop``peek`),并且在 Deque 接口中已经实现了相关方法。Stack 类已经和 Vector 一样被遗弃,现在在 Java 中普遍使用双端队列Deque来实现栈。
- 广度优先搜索BFS在图的广度优先搜索过程中,队列被用于存储待访问的节点,保证按照层次顺序遍历图的节点。
- **线程池中的请求/任务队列:** 线程池中没有空闲线程时,新的任务请求线程资源会被如何处理呢?答案是这些任务会被放入任务队列中,等待线程池中的线程空闲后再从队列中取出任务执行。任务队列分为无界队列(基于链表实现)和有界队列(基于数组实现)。无界队列的特点是队列容量理论上没有限制,任务可以持续入队,直到系统资源耗尽。例如:`FixedThreadPool` 使用的阻塞队列 `LinkedBlockingQueue`,其默认容量为 `Integer.MAX_VALUE`,因此可以被视为“无界队列”。而有界队列则不同,当队列已满时,如果再有新任务提交,由于队列无法继续容纳任务,线程池会拒绝这些任务,并抛出 `java.util.concurrent.RejectedExecutionException` 异常。
- ****:双端队列天生便可以实现栈的全部功能(`push``pop``peek`),并且在 Deque 接口中已经实现了相关方法。Stack 类已经和 Vector 一样被遗弃,现在在 Java 中普遍使用双端队列Deque来实现栈。
- **广度优先搜索BFS**在图的广度优先搜索过程中,队列被用于存储待访问的节点,保证按照层次顺序遍历图的节点。
- Linux 内核进程队列(按优先级排队)
- 现实生活中的派对,播放器上的播放列表;
- 消息队列

View File

@ -114,6 +114,16 @@ PS篇幅问题我这并没有对上面提到的分布式缓存选型做详
Redis 除了可以用作缓存之外,还可以用于分布式锁、限流、消息队列、延时队列等场景,功能强大!
### 为什么用 Redis 而不用本地缓存呢?
| 特性 | 本地缓存 | Redis |
| ------------ | ------------------------------------ | -------------------------------- |
| 数据一致性 | 多服务器部署时存在数据不一致问题 | 数据一致 |
| 内存限制 | 受限于单台服务器内存 | 独立部署,内存空间更大 |
| 数据丢失风险 | 服务器宕机数据丢失 | 可持久化,数据不易丢失 |
| 管理维护 | 分散,管理不便 | 集中管理,提供丰富的管理工具 |
| 功能丰富性 | 功能有限,通常只提供简单的键值对存储 | 功能丰富,支持多种数据结构和功能 |
### 常见的缓存读写策略有哪些?
关于常见的缓存读写策略的详细介绍,可以看我写的这篇文章:[3 种常用的缓存读写策略详解](https://javaguide.cn/database/redis/3-commonly-used-cache-read-and-write-strategies.html) 。

View File

@ -19,7 +19,7 @@ tag:
### 消息队列为什么会出现?
消息队``列算是作为后端程序员的一个必备技能吧,因为**分布式应用必定涉及到各个系统之间的通信问题**,这个时候消息队列也应运而生了。可以说分布式的产生是消息队列的基础,而分布式怕是一个很古老的概念了吧,所以消息队列也是一个很古老的中间件了。
消息队列算是作为后端程序员的一个必备技能吧,因为**分布式应用必定涉及到各个系统之间的通信问题**,这个时候消息队列也应运而生了。可以说分布式的产生是消息队列的基础,而分布式怕是一个很古老的概念了吧,所以消息队列也是一个很古老的中间件了。
### 消息队列能用来干什么?

View File

@ -89,14 +89,6 @@ Finally
**注意:不要在 finally 语句块中使用 return!** 当 try 语句和 finally 语句中都有 return 语句时try 语句块中的 return 语句会被忽略。这是因为 try 语句中的 return 返回值会先被暂存在一个本地变量中,当执行到 finally 语句中的 return 之后,这个本地变量的值就变为了 finally 语句中的 return 返回值。
[jvm 官方文档](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.10.2.5)中有明确提到:
> If the `try` clause executes a _return_, the compiled code does the following:
>
> 1. Saves the return value (if any) in a local variable.
> 2. Executes a _jsr_ to the code for the `finally` clause.
> 3. Upon return from the `finally` clause, returns the value saved in the local variable.
代码示例:
```java

View File

@ -276,23 +276,21 @@ TTL 改造的地方有两处:
另外,《阿里巴巴 Java 开发手册》中强制线程池不允许使用 `Executors` 去创建,而是通过 `ThreadPoolExecutor` 构造函数的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险
`Executors` 返回线程池对象的弊端如下:
`Executors` 返回线程池对象的弊端如下(后文会详细介绍到)
- `FixedThreadPool``SingleThreadExecutor`:使用的是有界阻塞队列是 `LinkedBlockingQueue` ,其任务队列的最大长度为 `Integer.MAX_VALUE` ,可能堆积大量的请求,从而导致 OOM。
- `FixedThreadPool``SingleThreadExecutor`:使用的是阻塞队列 `LinkedBlockingQueue`,任务队列最大长度为 `Integer.MAX_VALUE`,可以看作是无界的,可能堆积大量的请求,从而导致 OOM。
- `CachedThreadPool`:使用的是同步队列 `SynchronousQueue`, 允许创建的线程数量为 `Integer.MAX_VALUE` ,如果任务数量过多且执行速度较慢,可能会创建大量的线程,从而导致 OOM。
- `ScheduledThreadPool``SingleThreadScheduledExecutor` :使用的无界的延迟阻塞队列 `DelayedWorkQueue` ,任务队列最大长度为 `Integer.MAX_VALUE` 可能堆积大量的请求,从而导致 OOM。
- `ScheduledThreadPool``SingleThreadScheduledExecutor`:使用的无界的延迟阻塞队列`DelayedWorkQueue`,任务队列最大长度为 `Integer.MAX_VALUE`,可能堆积大量的请求,从而导致 OOM。
```java
// 有界队列 LinkedBlockingQueue
public static ExecutorService newFixedThreadPool(int nThreads) {
// LinkedBlockingQueue 的默认长度为 Integer.MAX_VALUE可以看作是无界的
return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
// 无界队列 LinkedBlockingQueue
public static ExecutorService newSingleThreadExecutor() {
// LinkedBlockingQueue 的默认长度为 Integer.MAX_VALUE可以看作是无界的
return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}
@ -885,6 +883,8 @@ public FutureTask(Runnable runnable, V result) {
`FutureTask`相当于对`Callable` 进行了封装,管理着任务执行的情况,存储了 `Callable``call` 方法的任务执行结果。
关于更多 `Future` 的源码细节,可以肝这篇万字解析,写的很清楚:[Java是如何实现Future模式的万字详解](https://juejin.cn/post/6844904199625375757)。
### CompletableFuture 类有什么用?
`Future` 在实际使用过程中存在一些局限性比如不支持异步任务的编排组合、获取计算结果的 `get()` 方法为阻塞调用。

View File

@ -13,7 +13,7 @@ tag:
`Executors` 返回线程池对象的弊端如下(后文会详细介绍到)
- **`FixedThreadPool``SingleThreadExecutor`**:使用的是有界阻塞队列 `LinkedBlockingQueue`,任务队列的默认长度和最大长度为 `Integer.MAX_VALUE`,可能堆积大量的请求,从而导致 OOM。
- **`FixedThreadPool``SingleThreadExecutor`**:使用的是阻塞队列 `LinkedBlockingQueue`,任务队列的默认长度和最大长度为 `Integer.MAX_VALUE`,可以看作是无界队列,可能堆积大量的请求,从而导致 OOM。
- **`CachedThreadPool`**:使用的是同步队列 `SynchronousQueue`,允许创建的线程数量为 `Integer.MAX_VALUE` ,可能会创建大量线程,从而导致 OOM。
- **`ScheduledThreadPool``SingleThreadScheduledExecutor`** : 使用的无界的延迟阻塞队列`DelayedWorkQueue`,任务队列最大长度为 `Integer.MAX_VALUE`,可能堆积大量的请求,从而导致 OOM。

View File

@ -183,21 +183,19 @@ public static class CallerRunsPolicy implements RejectedExecutionHandler {
`Executors` 返回线程池对象的弊端如下(后文会详细介绍到)
- `FixedThreadPool``SingleThreadExecutor`:使用的是无界的 `LinkedBlockingQueue`,任务队列最大长度为 `Integer.MAX_VALUE`,可能堆积大量的请求,从而导致 OOM。
- `FixedThreadPool``SingleThreadExecutor`:使用的是阻塞队列 `LinkedBlockingQueue`,任务队列最大长度为 `Integer.MAX_VALUE`,可以看作是无界的,可能堆积大量的请求,从而导致 OOM。
- `CachedThreadPool`:使用的是同步队列 `SynchronousQueue`, 允许创建的线程数量为 `Integer.MAX_VALUE` ,如果任务数量过多且执行速度较慢,可能会创建大量的线程,从而导致 OOM。
- `ScheduledThreadPool``SingleThreadScheduledExecutor`:使用的无界的延迟阻塞队列`DelayedWorkQueue`,任务队列最大长度为 `Integer.MAX_VALUE`,可能堆积大量的请求,从而导致 OOM。
```java
// 无界队列 LinkedBlockingQueue
public static ExecutorService newFixedThreadPool(int nThreads) {
// LinkedBlockingQueue 的默认长度为 Integer.MAX_VALUE可以看作是无界的
return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
// 无界队列 LinkedBlockingQueue
public static ExecutorService newSingleThreadExecutor() {
// LinkedBlockingQueue 的默认长度为 Integer.MAX_VALUE可以看作是无界的
return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}

View File

@ -20,7 +20,7 @@ Java IO 流的 40 多个类都是从如下 4 个抽象类基类中派生出来
## 字节流
### InputStream字节输入流
`InputStream`用于从源头(通常是文件)读取数据(字节信息)到内存中,`java.io.InputStream`抽象类是所有字节输入流的父类。
`InputStream` 常用方法:
@ -430,7 +430,7 @@ class BufferedInputStream extends FilterInputStream {
### BufferedOutputStream字节缓冲输出流
`BufferedOutputStream` 将数据(字节信息)写入到目的地(通常是文件)的过程中不会一个字节一个字节的写入,而是会先将要写入的字节存放在缓存区,并从内部缓冲区中单独写入字节。这样大幅减少了 IO 次数,提高了读取效率
`BufferedOutputStream` 将数据(字节信息)写入到目的地(通常是文件)的过程中不会一个字节一个字节的写入,而是会先将要写入的字节存放在缓存区,并从内部缓冲区中单独写入字节。这样大幅减少了 IO 次数,提高了效率
```java
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) {

View File

@ -83,7 +83,7 @@ tag:
**Docker 思想**
- **集装箱**就像海运中的集装箱一样Docker 容器包含了应用程序及其所有依赖项,确保在任何环境中都能以相同的方式运行。
- **标准化**运输方式、存储方式、API 接口。
- **标准化**运输方式、存储方式、API 接口。
- **隔离**:每个 Docker 容器都在自己的隔离环境中运行,与宿主机和其他容器隔离。
### Docker 容器的特点