JCIP-6-Task Execution

本文详细介绍了如何使用Java的Executor框架来管理和优化并发任务的执行,包括创建线程池、执行策略、延迟和周期性任务处理等,旨在帮助开发者最大化应用性能并避免线程创建带来的资源消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6-Task Execution
6.1-Executing tasks in threads
6.1.1. Executing Tasks Sequentially
6.1.2. Explicitly Creating Threads for Tasks
6.1.3. Disadvantages of Unbounded Thread Creation
Thread lifecycle overhead. Thread creation and teardown are not free
Resource consumption. When there are more runnable
threads than available processors, threads sit idle.Having many idle threads can tie up a lot of memory.
Stability. it is far easier to structure your program to avoid hitting this limit.Up to a certain point, more threads can improve throughput, but beyond that point creating more threads just slows
down your application
On 32-bit machines, a major limiting factor is address space for thread stacks. Each thread maintains two execution stacks, one for Java code
and one for native code.
6.2-The Executor framework
6.2.1. Example: Web Server Using Executor
java.util.concurrent provides a flexible thread
pool implementation as part of the Executor framework.
It provides a standard means of decoupling task
submission from task execution, describing tasks with Runnable.
Using
an Executor is usually the easiest path to implementing a producer-consumer design in your application.
6.2.2. Execution Policies
An execution policy specifies the “what, where, when, and
how” of task execution
Whenever you see code of the form:new Thread(runnable).start() seriously consider replacing it with the use
of an Executor.
6.2.3. Thread Pools
newFixedThreadPool
keep the pool size constant (adding new threads if a thread dies
newCachedThreadPool
add new threads when demand increases
newSingleThreadExecutor
replacing it if it dies unexpectedly.
newScheduledThreadPool
A fixed-size thread pool that supports delayed and periodic task execution
6.2.4. Executor Lifecycle
But the JVM can’t exit until all the (non-daemon) threads have terminated,so failing to
shut down an Executor could prevent the JVM from exiting.
The lifecycle implied by ExecutorService has three states: running, shutting down, and terminated. The shutdownNow method initiates an abrupt shutdown: it attempts to cancel outstanding tasks and
does not start any tasks that are queued but not begun.
You can wait for an ExecutorService to reach the terminated state with awaitTermination, It is common to follow shutdown immediately by awaitTermination, creating
the effect of synchronously shutting down the ExecutorService.
6.2.5. Delayed and Periodic Tasks
The Timer facility manages the execution of deferred and periodic tasks. However, Timer has some drawbacks, and ScheduledThreadPoolExecutor should be thought of as its
replacement.
Timer does have support for scheduling based on absolute, not relative time, so that tasks can be sensitive to changes in the system clock;
ScheduledThreadPoolExecutor supports only relative time.
A Timer creates only a single thread for executing timer tasks.Scheduled
thread pools address this limitation by letting you provide multiple threads for executing deferred and periodic tasks.
so an unchecked exception thrown from a TimerTask terminates the timer thread. Timer
also doesn’t resurrect the thread in this situation; instead, it erroneously assumes the entire Timer was cancelled. ScheduledThreadPoolExecutor deals
properly with ill-behaved tasks; there is little reason to use Timer in Java 5.0 or later.
DelayQueue, a BlockingQueue implementation that provides the scheduling functionality of
ScheduledThreadPoolExecutor.
6.3-Finding exploitable parallelism
6.3.1. Example: Sequential Page Renderer
6.3.2. Result-bearing Tasks: Callable and Future
Runnable is a fairly limiting abstraction; run
cannot return a value or throw checked exceptions.
For these types of tasks, Callable is a better abstraction: it expects that the main
entry point, call, will return a value and anticipates that it might throw an exception.
To express a non-value-returning task with Callable, use Callable.
a task executed by an Executor has four phases: created, submitted,
started, and completed.
Future represents the lifecycle of a task and provides methods to test whether the task has completed or been
cancelled, retrieve its result, and cancel the task.
Future.get:It returns immediately or
throws an Exception if the task has already completed, but if not it blocks until the task completes.If get throws ExecutionException, the underlying exception can be retrieved with
getCause.
Future.get deals with two possible problems: that the task encountered an Exception, or the thread
calling get was interrupted before the results were available.
6.3.3. Example: Page Renderer with Future
6.3.4. Limitations of Parallelizing Heterogeneous Tasks
6.3.5. CompletionService: Executor Meets BlockingQueue
CompletionService combines the functionality of an Executor and a BlockingQueue. You can submit Callable tasks
to it for execution and use the queue-like methods take and poll to retrieve completed results, packaged as Futures,
as they become available. ExecutorCompletionService implements CompletionService, delegating the computation
to an Executor.
When a task is submitted, it is wrapped with a QueueingFuture, a subclass of FutureTask that overrides
done to place the result on the BlockingQueue,
6.3.6. Example: Page Renderer with CompletionService
6.3.7. Placing Time Limits on Tasks
The timed version of Future.get supports this
requirement: it returns as soon as the result is ready, but throws TimeoutException if the result is not ready within the
timeout period.
if a timed get completes with a TimeoutException, you can cancel the task through the
Future.
6.3.8. Example: A Travel Reservations Portal
The invokeAll method takes a collection of tasks and returns a collection of Futures. The two collections have
identical structures; invokeAll adds the Futures to the returned collection in the order imposed by the task collection’s
iterator, thus allowing the caller to associate a Future with the Callable it represents.
Summary
The
Executor framework permits you to decouple task submission from execution policy and supports a rich variety of
execution policies; whenever you find yourself creating threads to perform tasks, consider using an Executor instead.
To maximize the benefit of decomposing an application into tasks, you must identify sensible task boundaries.
Summary
6.1-Executing tasks in threads
6.1.1. Executing Tasks Sequentially
6.1.2. Explicitly Creating Threads for Tasks
6.1.3. Disadvantages of Unbounded Thread Creation
Thread lifecycle overhead. Thread creation and teardown are not free
Resource consumption. When there are more runnable
threads than available processors, threads sit idle.Having many idle threads can tie up a lot of memory.
Stability. it is far easier to structure your program to avoid hitting this limit.Up to a certain point, more threads can improve throughput, but beyond that point creating more threads just slows
down your application
On 32-bit machines, a major limiting factor is address space for thread stacks. Each thread maintains two execution stacks, one for Java code
and one for native code.
6.2-The Executor framework
6.2.1. Example: Web Server Using Executor
java.util.concurrent provides a flexible thread
pool implementation as part of the Executor framework.
It provides a standard means of decoupling task
submission from task execution, describing tasks with Runnable.
Using
an Executor is usually the easiest path to implementing a producer-consumer design in your application.
6.2.2. Execution Policies
An execution policy specifies the “what, where, when, and
how” of task execution
Whenever you see code of the form:new Thread(runnable).start() seriously consider replacing it with the use
of an Executor.
6.2.3. Thread Pools
newFixedThreadPool
keep the pool size constant (adding new threads if a thread dies
newCachedThreadPool
add new threads when demand increases
newSingleThreadExecutor
replacing it if it dies unexpectedly.
newScheduledThreadPool
A fixed-size thread pool that supports delayed and periodic task execution
6.2.4. Executor Lifecycle
But the JVM can’t exit until all the (non-daemon) threads have terminated,so failing to
shut down an Executor could prevent the JVM from exiting.
The lifecycle implied by ExecutorService has three states: running, shutting down, and terminated. The shutdownNow method initiates an abrupt shutdown: it attempts to cancel outstanding tasks and
does not start any tasks that are queued but not begun.
You can wait for an ExecutorService to reach the terminated state with awaitTermination, It is common to follow shutdown immediately by awaitTermination, creating
the effect of synchronously shutting down the ExecutorService.
6.2.5. Delayed and Periodic Tasks
The Timer facility manages the execution of deferred and periodic tasks. However, Timer has some drawbacks, and ScheduledThreadPoolExecutor should be thought of as its
replacement.
Timer does have support for scheduling based on absolute, not relative time, so that tasks can be sensitive to changes in the system clock;
ScheduledThreadPoolExecutor supports only relative time.
A Timer creates only a single thread for executing timer tasks.Scheduled
thread pools address this limitation by letting you provide multiple threads for executing deferred and periodic tasks.
so an unchecked exception thrown from a TimerTask terminates the timer thread. Timer
also doesn’t resurrect the thread in this situation; instead, it erroneously assumes the entire Timer was cancelled. ScheduledThreadPoolExecutor deals
properly with ill-behaved tasks; there is little reason to use Timer in Java 5.0 or later.
DelayQueue, a BlockingQueue implementation that provides the scheduling functionality of
ScheduledThreadPoolExecutor.
6.3-Finding exploitable parallelism
6.3.1. Example: Sequential Page Renderer
6.3.2. Result-bearing Tasks: Callable and Future
Runnable is a fairly limiting abstraction; run
cannot return a value or throw checked exceptions.
For these types of tasks, Callable is a better abstraction: it expects that the main
entry point, call, will return a value and anticipates that it might throw an exception.
To express a non-value-returning task with Callable, use Callable.
a task executed by an Executor has four phases: created, submitted,
started, and completed.
Future represents the lifecycle of a task and provides methods to test whether the task has completed or been
cancelled, retrieve its result, and cancel the task.
Future.get:It returns immediately or
throws an Exception if the task has already completed, but if not it blocks until the task completes.If get throws ExecutionException, the underlying exception can be retrieved with
getCause.
Future.get deals with two possible problems: that the task encountered an Exception, or the thread
calling get was interrupted before the results were available.
6.3.3. Example: Page Renderer with Future
6.3.4. Limitations of Parallelizing Heterogeneous Tasks
6.3.5. CompletionService: Executor Meets BlockingQueue
CompletionService combines the functionality of an Executor and a BlockingQueue. You can submit Callable tasks
to it for execution and use the queue-like methods take and poll to retrieve completed results, packaged as Futures,
as they become available. ExecutorCompletionService implements CompletionService, delegating the computation
to an Executor.
When a task is submitted, it is wrapped with a QueueingFuture, a subclass of FutureTask that overrides
done to place the result on the BlockingQueue,
6.3.6. Example: Page Renderer with CompletionService
6.3.7. Placing Time Limits on Tasks
The timed version of Future.get supports this
requirement: it returns as soon as the result is ready, but throws TimeoutException if the result is not ready within the
timeout period.
if a timed get completes with a TimeoutException, you can cancel the task through the
Future.
6.3.8. Example: A Travel Reservations Portal
The invokeAll method takes a collection of tasks and returns a collection of Futures. The two collections have
identical structures; invokeAll adds the Futures to the returned collection in the order imposed by the task collection’s
iterator, thus allowing the caller to associate a Future with the Callable it represents.
Summary
The
Executor framework permits you to decouple task submission from execution policy and supports a rich variety of
execution policies; whenever you find yourself creating threads to perform tasks, consider using an Executor instead.
To maximize the benefit of decomposing an application into tasks, you must identify sensible task boundaries.
Summary

DISSIDIA思维导图

### VMware 16 Multi-Execution 功能说明 VMware Workstation Pro 16 引入了一项名为 **Multi-Execution** 的功能,该功能允许用户在同一虚拟机上并行运行多个不同的执行路径[^6]。这一特性对于调试复杂的程序行为、测试不确定性的应用程序逻辑以及探索分支条件非常有用。 #### 多执行的核心概念 多执行通过模拟同一虚拟机的不同实例来捕捉可能的分支路径。它能够自动检测到可能导致状态变化的操作(例如随机数生成器调用或非确定性输入),并将这些操作分叉成独立的执行流。每条执行路径都可以被单独保存、回放和分析[^7]。 #### 配置方法 以下是启用和配置 VMware Workstation Pro 中 Multi-Execution 的基本流程: 1. 创建一个新的虚拟机或将现有虚拟机迁移到支持的工作站版本。 2. 启动虚拟机后,在菜单栏中找到 `Debug` 菜单下的选项 `Start Recording with Multi-Execution`[^8]。这一步骤将启动多执行模式,并开始跟踪所有潜在的状态分歧点。 ```bash # 如果需要手动调整设置,可以通过编辑 .vmx 文件完成进一步定制 vim your_vm_name.vmx # 添加或多执行相关参数如下: replay.multiexecution.enabled = "TRUE" ``` 3. 当虚拟机遇到不确定性事件时,Workstation 自动创建新的执行分支。用户可以在 GUI 界面中的树形视图查看各个分支及其差异[^9]。 4. 使用内置工具比较各分支的结果数据,定位特定条件下产生的错误或异常情况。 #### 技术优势 相比传统的单一重播机制,多执行提供了更强大的能力去重现难以捕获的问题场景。尤其适用于开发人员排查间歇性崩溃或者依赖外部环境变量的应用缺陷[^10]。 ```python # 示例 Python 测试脚本用于验证多执行效果 import random def test_function(): choice = random.randint(0, 1) if choice == 0: print("Branch A Selected") else: print("Branch B Selected") test_function() ``` 上述代码片段展示了如何利用随机函数触发两条不同路径的选择。借助于 multi-execution 特性,可以轻松观察两种可能性的实际表现而无需反复尝试。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值