提交 234ae965 编写于 作者: W wizardforcel

2020-05-22 23:14:04

上级 799cd92f
......@@ -2,7 +2,7 @@
> 原文: [https://howtodoinjava.com/java-concurrency-tutorial/](https://howtodoinjava.com/java-concurrency-tutorial/)
简而言之, [**并发**](https://en.wikipedia.org/wiki/Concurrency_%28computer_science%29) 是并行运行多个程序或程序的多个部分的能力。 并发使程序可以通过利用底层操作系统和机器硬件的未开发功能来实现高性能和吞吐量。 例如现代计算机在一个 CPU 中具有多个 CPU 或多个内核,程序可以将所有内核用于处理的某些部分; 因此,与顺序处理相比,可以更早地完成任务。
简而言之,[**并发**](https://en.wikipedia.org/wiki/Concurrency_%28computer_science%29)是并行运行多个程序或程序的多个部分的能力。 并发使程序可以通过利用底层操作系统和机器硬件的未开发功能来实现高性能和吞吐量。 例如现代计算机在一个 CPU 中具有多个 CPU 或多个内核,程序可以将所有内核用于处理的某些部分; 因此,与顺序处理相比,可以更早地完成任务。
**Java 并发**的主干是线程。 线程是一个轻量级进程,它具有自己的调用堆栈,但可以访问同一进程中其他线程的共享数据。 Java 应用程序默认在一个进程中运行。 在 Java 应用程序中,您可以使用许多线程来实现并行处理或并发。
......@@ -24,49 +24,72 @@
## Java 并发教程
在单个帖子中涵盖整个 Java 并发几乎是不可能的。 因此,我在下面的 Java Concurrency Tutorials 中编写了一篇文章,讨论了一个单独的概念。 浏览这些教程,如果您有任何问题或建议,请告诉我。
在单个帖子中涵盖整个 Java 并发几乎是不可能的。 因此,我在下面的 Java 并发教程中编写了一篇文章,讨论了一个单独的概念。 浏览这些教程,如果您有任何问题或建议,请告诉我。
#### Java 并发基础
[并发演化](//howtodoinjava.com/java/multi-threading/java-multi-threading-evolution-and-topics/)
[什么是线程安全性?](//howtodoinjava.com/java/multi-threading/what-is-thread-safety/)
[对象级锁定和类级锁定](//howtodoinjava.com/java/multi-threading/thread-synchronization-object-level-locking-and-class-level-locking/)
[比较和交换[CAS]算法](//howtodoinjava.com/java/multi-threading/compare-and-swap-cas-algorithm/)
[wait(),notify()和 notifyAll ()方法](//howtodoinjava.com/java/multi-threading/how-to-work-with-wait-notify-and-notifyall-in-java/)
[比较和交换(CAS)算法](//howtodoinjava.com/java/multi-threading/compare-and-swap-cas-algorithm/)
[`wait()`,`notify()`和`notifyAll()`方法](//howtodoinjava.com/java/multi-threading/how-to-work-with-wait-notify-and-notifyall-in-java/)
#### 之间的区别
[“可运行的实现”和“扩展线程”之间的区别](//howtodoinjava.com/java/multi-threading/difference-between-implements-runnable-and-extends-thread-in-java/)
[“`Runnable`实现”和“扩展线程”之间的区别](//howtodoinjava.com/java/multi-threading/difference-between-implements-runnable-and-extends-thread-in-java/)
[锁和监视器之间的区别](//howtodoinjava.com/java/multi-threading/multithreading-difference-between-lock-and-monitor/)
[yield()和 join()之间的区别](//howtodoinjava.com/java/multi-threading/difference-between-yield-and-join-in-threads-in-java/) [
[sleep()和 wait()之间的区别?](//howtodoinjava.com/java/multi-threading/difference-between-sleep-and-wait/)
[`yield()`和`join()`之间的区别](//howtodoinjava.com/java/multi-threading/difference-between-yield-and-join-in-threads-in-java/) [
[`sleep()`和`wait()`之间的区别?](//howtodoinjava.com/java/multi-threading/difference-between-sleep-and-wait/)
#### 执行器框架
[执行程序框架教程](//howtodoinjava.com/java-5/java-executor-framework-tutorial-and-best-practices/)
[ScheduledThreadPoolExecutor 示例](//howtodoinjava.com/2015/03/25/task-scheduling-with-executors-scheduledthreadpoolexecutor-example/)
[FixedSizeThreadPoolExecutor 示例](//howtodoinjava.com/java/multi-threading/java-fixed-size-thread-pool-executor-example/)
[ThreadPoolExecutor 示例](//howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example/)
[可调用+将来的示例](//howtodoinjava.com/java/multi-threading/threadpoolexecutor-callable-future-example/)
[使用 ThreadPoolExecutor 和 Semaphore 限制任务提交率](//howtodoinjava.com/java/multi-threading/throttling-task-submission-rate-using-threadpoolexecutor-and-semaphore/)
[BlockingQueue 示例](//howtodoinjava.com/java-5/how-to-use-blockingqueue-and-threadpoolexecutor-in-java/)
[UncaughtExceptionHandler 示例](//howtodoinjava.com/java/multi-threading/how-to-restart-thread-using-uncaughtexceptionhandler/)
[执行器框架教程](//howtodoinjava.com/java-5/java-executor-framework-tutorial-and-best-practices/)
[`ScheduledThreadPoolExecutor`示例](//howtodoinjava.com/2015/03/25/task-scheduling-with-executors-scheduledthreadpoolexecutor-example/)
[`FixedSizeThreadPoolExecutor`示例](//howtodoinjava.com/java/multi-threading/java-fixed-size-thread-pool-executor-example/)
[`ThreadPoolExecutor`示例](//howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example/)
[`Runnable`+`Future`的示例](//howtodoinjava.com/java/multi-threading/threadpoolexecutor-callable-future-example/)
[使用`ThreadPoolExecutor`和`Semaphore`限制任务提交率](//howtodoinjava.com/java/multi-threading/throttling-task-submission-rate-using-threadpoolexecutor-and-semaphore/)
[`BlockingQueue`示例](//howtodoinjava.com/java-5/how-to-use-blockingqueue-and-threadpoolexecutor-in-java/)
[`UncaughtExceptionHandler`示例](//howtodoinjava.com/java/multi-threading/how-to-restart-thread-using-uncaughtexceptionhandler/)
#### 并发
[ForkJoinPool 示例](//howtodoinjava.com/java-7/forkjoin-framework-tutorial-forkjoinpool-example/)
[CountDownLatch 示例](//howtodoinjava.com/java/multi-threading/when-to-use-countdownlatch-java-concurrency-example-tutorial/)
[`ForkJoinPool`示例](//howtodoinjava.com/java-7/forkjoin-framework-tutorial-forkjoinpool-example/)
[`CountDownLatch`示例](//howtodoinjava.com/java/multi-threading/when-to-use-countdownlatch-java-concurrency-example-tutorial/)
[使用信号量](//howtodoinjava.com/java/multi-threading/control-concurrent-access-to-multiple-copies-of-a-resource-using-semaphore/)
[BinarySemaphore](//howtodoinjava.com/java/multi-threading/binary-semaphore-tutorial-and-example/)
[Java .util.concurrent.locks.Lock](//howtodoinjava.com/java/multi-threading/how-to-use-locks-in-java-java-util-concurrent-locks-lock-tutorial-and-example/)
[java.util.concurrent.ThreadFactory](//howtodoinjava.com/java/multi-threading/creating-threads-using-java-util-concurrent-threadfactory/)
[`BinarySemaphore`](//howtodoinjava.com/java/multi-threading/binary-semaphore-tutorial-and-example/)
[`Java.util.concurrent.locks.Lock`](//howtodoinjava.com/java/multi-threading/how-to-use-locks-in-java-java-util-concurrent-locks-lock-tutorial-and-example/)
[`java.util.concurrent.ThreadFactory`](//howtodoinjava.com/java/multi-threading/creating-threads-using-java-util-concurrent-threadfactory/)
[线程局部变量](//howtodoinjava.com/java/multi-threading/when-and-how-to-use-thread-local-variables/)
[线程间通信](//howtodoinjava.com/java/multi-threading/inter-thread-communication-using-piped-streams-in-java/)
#### 并发收藏
#### 并发集合
[`ConcurrentHashMap`示例](//howtodoinjava.com/java/collections/best-practices-for-using-concurrenthashmap/)
[ConcurrentHashMap 示例](//howtodoinjava.com/java/collections/best-practices-for-using-concurrenthashmap/)
[ConcurrentLinkedDeque 示例](//howtodoinjava.com/java/multi-threading/non-blocking-thread-safe-list-concurrentlinkeddeque-example/)
[`ConcurrentLinkedDeque`示例](//howtodoinjava.com/java/multi-threading/non-blocking-thread-safe-list-concurrentlinkeddeque-example/)
#### 杂
......
......@@ -8,7 +8,7 @@
## JDK 发行版明智的多线程概念
根据 [**JDK 1.x 发行版**](https://www.cs.princeton.edu/courses/archive/fall97/cs461/jdkdocs/) ,在此初始发行版中仅存在很少的类。 具体来说,这些类/接口是:
根据 [**JDK 1.x 发行版**](https://www.cs.princeton.edu/courses/archive/fall97/cs461/jdkdocs/),在此初始发行版中仅存在很少的类。 具体来说,这些类/接口是:
* `java.lang.Thread`
* `java.lang.ThreadGroup`
......@@ -31,17 +31,17 @@
[**JDK 1.5**](https://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html) 是 JDK 1.x 之后的第一个大版本; 它包括多个并发实用程序。 `Executor``semaphore``mutex``barrier``latches``concurrent collections``blocking queues`; 所有内容均包含在此版本本身中。 Java 多线程应用程序云的最大变化发生在此版本中。
> 阅读此链接中的全部更改: [http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html](https://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html)
> 阅读此链接中的全部更改: [http://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html](https://docs.oracle.com/javase/1.5.0/docs/guide/concurrency/overview.html)
**JDK 1.6** 更多的是平台修复,而不是 API 升级。 因此,JDK 1.6 中出现了新变化。
[**JDK 1.7**](https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/changes7.html) 添加了对`ForkJoinPool`的支持,该支持实现了**工作窃听技术**以使吞吐量最大化。 还添加了`Phaser`类。
[**JDK 1.8**](https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html) 因 Lambda 更改而广为人知,但并发更改也很少。 在 **java.util.concurrent** 包中添加了两个新接口和四个新类。 `CompletableFuture``CompletionException`
[**JDK 1.8**](https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html) 因 Lambda 更改而广为人知,但并发更改也很少。 在`java.util.concurrent`包中添加了两个新接口和四个新类。 `CompletableFuture``CompletionException`
Collections Framework 在 Java 8 中进行了重大修订,以基于新添加的**流工具****lambda 表达式**添加聚合操作; 导致在几乎所有`Collection`类中以及在并发集合中添加了大量方法。
集合框架在 Java 8 中进行了重大修订,以基于新添加的**流工具****lambda 表达式**添加聚合操作; 导致在几乎所有`Collection`类中以及在并发集合中添加了大量方法。
> 阅读此链接中的全部更改: [http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html](https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html)
> 阅读此链接中的全部更改: [http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html](https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html)
#### 参考文献:
......@@ -52,6 +52,6 @@ Collections Framework 在 Java 8 中进行了重大修订,以基于新添加
* [http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html](http://www.oracle.com/technetwork/java/javase/jdk7-relnotes-418459.html)
* [http://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html](https://docs.oracle.com/javase/8/docs/technotes/guides/concurrency/changes8.html)
我希望上面的清单可以帮助您理解**多线程功能(JDK 版本明智的**)。
我希望上面的清单可以帮助您理解**多线程功能(每个 JDK 版本**)。
学习愉快!
\ No newline at end of file
......@@ -9,11 +9,11 @@
并且还有更多类似的定义。
您难道不认为上述定义实际上并没有传达任何有意义的信息,甚至还会增加一些混乱。 尽管不能完全排除这些定义,因为它们没有错。 但是事实是**他们没有提供任何实际的帮助或观点**。 我们如何在线程安全类和不安全类之间区分**? **“安全”** 甚至意味着什么?**
您难道不认为上述定义实际上并没有传达任何有意义的信息,甚至还会增加一些混乱。 尽管不能完全排除这些定义,因为它们没有错。 但是事实是**他们没有提供任何实际的帮助或观点**。 我们如何在线程安全类和不安全类之间区分?“**安全**”甚至意味着什么?
## 什么是线程安全的正确性?
线程安全性的任何合理定义的核心是正确性的概念。 因此,在了解线程安全性之前,我们应该首先了解“ `correctness`”。
线程安全性的任何合理定义的核心是正确性的概念。 因此,在了解线程安全性之前,我们应该首先了解“正确性”。
> 正确性是指一个类符合其规范。
......@@ -44,6 +44,6 @@ public class StatelessFactorizer implements Servlet
特定计算的暂态仅存在于局部变量中,这些局部变量存储在线程的堆栈中,并且只有执行线程才能访问。 一个线程访问`StatelessFactorizer`不会影响另一线程访问同一`StatelessFactorizer`的结果; 因为两个线程不共享状态,所以好像它们正在访问不同的实例。 由于线程访问无状态对象的动作不会影响其他线程中操作的正确性,因此无状态对象是线程安全的。
这就是围绕**这个小而重要的概念的全部内容。什么是线程安全**
这就是围绕“什么是线程安全?”这个小而重要的概念的全部内容。
**祝您学习愉快!**
\ No newline at end of file
......@@ -2,7 +2,7 @@
> 原文: [https://howtodoinjava.com/java/multi-threading/compare-and-swap-cas-algorithm/](https://howtodoinjava.com/java/multi-threading/compare-and-swap-cas-algorithm/)
Java 5 中最好的补充之一是`AtomicInteger``AtomicLong`等类中支持的原子操作。这些类可帮助您将复杂的(不必要的) [**多线程[**](//howtodoinjava.com/category/java/multi-threading/ "multi-threading") 用于一些基本操作的代码,例如递增或递减在多个线程之间共享的值。 这些类在内部依赖于名为 **CAS(比较和交换)**的算法。 在本文中,我将详细讨论这个概念。
Java 5 中最好的补充之一是`AtomicInteger``AtomicLong`等类中支持的原子操作。这些类可帮助您将复杂的(不必要的)[**多线程**](//howtodoinjava.com/category/java/multi-threading/ "multi-threading")用于一些基本操作的代码,例如递增或递减在多个线程之间共享的值。 这些类在内部依赖于名为 CAS(比较和交换)的算法。 在本文中,我将详细讨论这个概念。
## 1\. 乐观锁和悲观锁
......@@ -24,23 +24,23 @@ Java 5 中最好的补充之一是`AtomicInteger`,`AtomicLong`等类中支持
CAS 操作有 3 个参数:
1. 必须替换值的存储位置 V
2. 线程上次读取的旧值 A
3. 新值 B 应该写在 V 上
1. 必须替换值的存储位置`V`
2. 线程上次读取的旧值`A`
3. 应该写在`V`上的新值`B`
> CAS 说:“我认为 V 应该具有值 A; 如果可以,则将 B 放在此处,否则不要更改它,但要告诉我我错了。” CAS 是一种乐观技术,它希望成功进行更新,并且自从上次检查变量以来,如果另一个线程更新了该变量,则可以检测到失败。
> CAS 说:“我认为`V`应该具有值`A`; 如果可以,则将`B`放在此处,否则不要更改它,但要告诉我我错了。” CAS 是一种乐观技术,它希望成功进行更新,并且自从上次检查变量以来,如果另一个线程更新了该变量,则可以检测到失败。
## 3\. Java 比较和交换示例
让我们通过一个例子来了解整个过程。 假设 V 是存储值“ 10”的存储位置。 有多个线程想要递增此值并将递增的值用于其他操作,这是一种非常实际的方案。 让我们分步介绍整个 CAS 操作:
让我们通过一个例子来了解整个过程。 假设`V`是存储值“10”的存储位置。 有多个线程想要递增此值并将递增的值用于其他操作,这是一种非常实际的方案。 让我们分步介绍整个 CAS 操作:
**1)线程 1 和 2 想要增加它,它们都读取值并将其增加到 11。**
*V = 10,A = 0,B = 0*
`V = 10, A = 0, B = 0`
**2)现在线程 1 首先出现,并将 V 与最后读取的值进行比较:**
**2)现在线程 1 首先出现,并将`V`与最后读取的值进行比较:**
*V = 10,A = 10,B = 11*
`V = 10, A = 10, B = 11`
```java
if     A = V
......@@ -50,11 +50,11 @@ if     A = V
   return V
```
显然,V 的值将被覆盖为 11,即操作成功。
显然,`V`的值将被覆盖为 11,即操作成功。
**3)线程 2 到来并尝试与线程 1** 相同的操作
**3)线程 2 到来并尝试与线程 1 相同的操作**
*V = 11,A = 10,B = 11*
`V = 11, A = 10, B = 11`
```java
if     A = V
......@@ -64,11 +64,11 @@ if     A = V
   return V
```
**4)在这种情况下,V 不等于 A,因此不替换值,并且返回 V 即 11 的当前值。 现在线程 2,再次使用以下值重试此操作:**
**4)在这种情况下,`V`不等于`A`,因此不替换值,并且返回`V`的当前值即 11。 现在线程 2,再次使用以下值重试此操作:**
*V = 11,A = 11,B = 12*
`V = 11, A = 11, B = 12`
而这一次,条件得到满足,增量值 12 返回线程 2。
而这一次,条件得到满足,线程 2 返回增量值 12。
总而言之,当多个线程尝试使用 CAS 同时更新同一变量时,一个将获胜并更新该变量的值,而其余则将丢失。 但是失败者并不会因为线程中断而受到惩罚。 他们可以自由地重试该操作,或者什么也不做。
......
......@@ -2,7 +2,7 @@
> 原文: [https://howtodoinjava.com/java/multi-threading/java-callable-future-example/](https://howtodoinjava.com/java/multi-threading/java-callable-future-example/)
[Java 执行程序框架](https://howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example/ "executor")的好处之一是,我们可以运行并发任务,这些并发任务在处理任务后可以返回单个结果。 [Java Concurrency](https://howtodoinjava.com/java-concurrency-tutorial/) API 通过以下两个接口[`**Callable**`](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/Callable.html "Callable")[`**Future**`](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/Future.html "Future")实现此目的。
[Java 执行框架](https://howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example/ "executor")的好处之一是,我们可以运行并发任务,这些并发任务在处理任务后可以返回单个结果。 [Java Concurrency](https://howtodoinjava.com/java-concurrency-tutorial/) API 通过以下两个接口[`**Callable**`](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/Callable.html "Callable")[`**Future**`](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/Future.html "Future")实现此目的。
## 1\. Java Callable 和 Future 接口
......@@ -111,7 +111,7 @@ Future result is - - 2; And Task done is true
```
在这里,我们使用`submit()`方法发送了一个`Callable`对象,该对象将在执行程序中执行。 此方法接收`Callable`对象作为参数,并返回一个`Future`对象,我们可以将其用于两个主要目标:
在这里,我们使用`submit()`方法发送了一个`Callable`对象,该对象将在执行中执行。 此方法接收`Callable`对象作为参数,并返回一个`Future`对象,我们可以将其用于两个主要目标:
1. **我们可以控制任务的状态** – 我们可以取消任务并检查任务是否完成。 为此,我们使用`isDone()`方法检查任务是否完成。
2. **We can get the result returned by the call() method**. For this purpose, we have used the `get()` method. This method waits until the `Callable` object has finished the execution of the `call()` method and has returned its result.
......
# Java 执行程序框架教程和最佳实践
# Java 执行框架教程和最佳实践
> 原文: [https://howtodoinjava.com/java/multi-threading/executor-framework-tutorial/](https://howtodoinjava.com/java/multi-threading/executor-framework-tutorial/)
与 JDK 5 一起发布的 [Java 执行程序框架](https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html "Executor framework")(java.util.concurrent.Executor)用于运行`Runnable`对象,而无需每次都创建新线程,并且主要是重新使用已经创建的线程。
与 JDK 5 一起发布的 [Java 执行框架](https://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html "Executor framework")(java.util.concurrent.Executor)用于运行`Runnable`对象,而无需每次都创建新线程,并且主要是重新使用已经创建的线程。
我们都知道有两种方法可以在 Java 中创建线程。 如果您想了解有关它们比较的更多信息,请阅读 [**如何在 Java**](//howtodoinjava.com/java/multi-threading/difference-between-implements-runnable-and-extends-thread-in-java/ "Difference between “implements Runnable” and “extends Thread” in java") 中创建线程。
在 Java 中创建线程是一个非常昂贵的过程,其中还包括内存开销。 因此,如果我们可以在创建后重新使用这些线程来运行将来的可运行对象,则是一个好主意。 在此**执行程序框架教程**中,我将编写一些演示程序来演示`Executor`的用法,然后我们将讨论在设计下一个多线程应用程序时需要牢记的一些最佳实践。
在 Java 中创建线程是一个非常昂贵的过程,其中还包括内存开销。 因此,如果我们可以在创建后重新使用这些线程来运行将来的可运行对象,则是一个好主意。 在此**执行框架教程**中,我将编写一些演示程序来演示`Executor`的用法,然后我们将讨论在设计下一个多线程应用程序时需要牢记的一些最佳实践。
## 1\. Java 执行程序框架示例
## 1\. Java 执行框架示例
在演示应用程序中,我们有两个任务正在运行。 两者都不会终止,并且都应在应用程序的生命周期内运行。 我将尝试编写一个主包装器类,例如:
......@@ -96,7 +96,7 @@ class TestTwo implements Runnable {
请不要忘记在帖子结尾阅读最佳实践。
## 2\. Java 执行程序框架 – 可多运行
## 2\. Java 执行框架 – 可多运行
不必每个`Runnable`都在单独的线程中执行。 有时,我们需要在单个线程中执行多个作业,并且每个作业都是`Runnable`的实例。 要设计此类解决方案,应使用**多可运行**。 这个多可运行对象不过是需要执行的可运行对象的集合。 唯一的补充是,该多可运行库本身也是**可运行库**
......@@ -212,7 +212,7 @@ class RejectedExecutionHandelerImpl implements RejectedExecutionHandler
```
## 3\. Java 执行程序框架最佳实践
## 3\. Java 执行框架最佳实践
1. 始终针对静态分析工具(例如 [PMD](http://pmd.sourceforge.net/ "pmd home page")[FindBugs](http://findbugs.sourceforge.net/ "findbugs home page") )运行 Java 代码,以查找更深层次的问题。 它们对于确定将来可能出现的丑陋情况非常有帮助。
2. 始终与高级人员进行交叉检查并更好地计划代码审查,以在执行过程中检测并可能在代码中出现[死锁或活动锁](https://en.wikipedia.org/wiki/Deadlock "deadlock and livelock")。 在大多数情况下,在应用程序中添加运行状况监视器以检查正在运行的任务的状态是一个很好的选择。
......
......@@ -160,7 +160,7 @@ public final class DiskFileManager
## 添加食流者
因此,我们已经添加了一个 bash 脚本和一个用于运行脚本的执行程序代码。 您必须编写自己的线程才能在执行程序上方定期运行。
因此,我们已经添加了一个 bash 脚本和一个用于运行脚本的执行器代码。 您必须编写自己的线程才能在执行器上方定期运行。
现在,我们将研究 StreamEater,它实际上收集命令输出并提供给您的应用程序代码,因此应用程序可以记录它或执行所需的任何操作。
......
......@@ -35,7 +35,7 @@ catch(Exception e) {
应用程序可能会以 N 种不同方式出错。 这就是为什么我们可以将**多个捕获块**与单个 try 块相关联的原因。 在每个 catch 块中,我们可以以一种独特的方式处理一个或多个特定的异常。
当一个 catch 块处理异常时,不执行下一个 catch 块。 控制直接从已执行的 catch 块转移到执行程序的其余部分,包括 finally 块。
当一个 catch 块处理异常时,不执行下一个 catch 块。 控制直接从已执行的 catch 块转移到执行的其余部分,包括 finally 块。
```java
try {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册