- 所有已知子接口:
ICancelTokenSource
public interface ICancelToken
取消令牌
2. 通过Future取消只能取消Future关联的任务,而不能取消一组相关的任务。要取消一组相关的任务,必须让这些任务共享同一个上下文 -- 即取消上下文。
取消令牌由任务持有,任务在执行期间可主动检测取消,并在检测到取消后抛出CancellationException,
如果不想打印堆栈,可抛出StacklessCancellationException。
首先,我们要明白为什么需要支持取消,当不再需要任务的结果时,及时取消任务的执行,以避免不必要的资源浪费。
在多年以前,多线程编程和异步编程尚不普遍,因此Future通常只与单个任务绑定,因此取消任务的最佳方式就是通过Future取消 —— 既清晰,又可以避免额外开销。
但在异步编程如火如荼的今天,通过Future取消任务越来越力不从心。
Future.cancel 的缺陷
1.Future.cancel(boolean)的接口约定是强制的,要求方法返回前Future必须进入完成状态,这是个错误的约定。
取消是协作式的,并不能保证立即成功 -- 取消一个任务和终止一个线程没有本质区别。2. 通过Future取消只能取消Future关联的任务,而不能取消一组相关的任务。要取消一组相关的任务,必须让这些任务共享同一个上下文 -- 即取消上下文。
如何中断线程
注意!取消令牌只是一个共享上下文,不具备任何其它功能。一个任务如果要响应中断信号,必须注册监听器,然后中断自身所在的线程。
public void run() {
// 在执行耗时操作前检查取消信号
cancelToken.checkCancel();
// 在执行阻塞操作前监听取消信号以唤醒线程
Thread thread = Thread.currentThread();
var handle = cancelToken.thenAccept(token -> {
thread.interrupt();
})
// 如果handle已被通知,那么线程已处于中断状态,阻塞操作会立即被中断
try (handle) {
blockingOp();
}
}
监听器
1. accept系列方法表示接收token参数;run方法表示不接收token参数; 2. async表示目标action需要异步执行,方法的首个参数为executor;监听器管理
用户除了可以通过返回的Registration删除监听器外,
还可以通过调度选项TaskOptions.STAGE_LISTEN_CANCEL_TOKEN要求当前取消令牌监听用户上下文中的取消令牌,
以及时删除不再需要执行的回调 -- 可以实现批量删除。
差异的源头: 取消令牌可能永远不会收到取消信号,而这可能是正常的需求,因此用户的监听器必须及时从监听器列表删除; 虽然不及时删除不会导致逻辑错误,但会导致内存泄漏。
- 作者:
- wjybxx date - 2024/1/8
-
字段概要
字段 -
方法概要
修饰符和类型方法说明boolean当前token是否可以进入取消状态int取消码 1.default void检测取消信号 如果收到取消信号,则抛出CancellationExceptiondefault boolean是否已收到取消信号 任务的执行者将持有该令牌,在调度任务前会检测取消信号;如果任务已经开始,则由用户的任务自身检测取消和中断信号。default intreason()取消的原因 (1~10为底层使用,10以上为用户自定义)TthenAccept(BiConsumer<? super ICancelToken, Object> action, Object ctx) thenAccept(BiConsumer<? super ICancelToken, Object> action, Object ctx, int options) 添加的action将在Token收到取消信号时执行 1.如果已收到取消请求,则给定的action会立即执行。thenAccept(Consumer<? super ICancelToken> action) thenAccept(Consumer<? super ICancelToken> action, int options) 添加的action将在Token收到取消信号时执行 1.如果已收到取消请求,则给定的action会立即执行。thenAcceptAsync(Executor executor, BiConsumer<? super ICancelToken, Object> action, Object ctx) thenAcceptAsync(Executor executor, BiConsumer<? super ICancelToken, Object> action, Object ctx, int options) thenAcceptAsync(Executor executor, Consumer<? super ICancelToken> action) thenAcceptAsync(Executor executor, Consumer<? super ICancelToken> action, int options) thenNotify(ICancelTokenListener action, Object ctx) thenNotify(ICancelTokenListener action, Object ctx, int options) 添加一个特定类型的监听器 (用于特殊需求时避免额外的闭包 - task经常需要监听取消令牌)thenNotifyAsync(Executor executor, ICancelTokenListener action, Object ctx) thenNotifyAsync(Executor executor, ICancelTokenListener action, Object ctx, int options) thenRunAsync(Executor executor, Runnable action) thenRunAsync(Executor executor, Runnable action, int options) thenRunAsync(Executor executor, Consumer<Object> action, Object ctx) thenRunAsync(Executor executor, Consumer<Object> action, Object ctx, int options) thenTransferTo(ICancelTokenSource child) thenTransferTo(ICancelTokenSource child, int options) 该接口用于方便构建子上下文 1.子token会在当前token进入取消状态时被取消 2.该接口本质是一个快捷方法,但允许子类优化thenTransferToAsync(Executor executor, ICancelTokenSource child) thenTransferToAsync(Executor executor, ICancelTokenSource child, int options)
-
字段详细资料
-
NONE
永不取消的Token
-
-
方法详细资料
-
canBeCancelled
boolean canBeCancelled()当前token是否可以进入取消状态- 返回:
- 如果当前token可以进入取消状态则返回true
-
cancelCode
int cancelCode()取消码 1. 按bit位存储信息,包括是否请求中断,是否超时,紧急程度等 2. 低20位为取消原因;高12位为特殊信息CancelCodes.MASK_REASON3. 不为0表示已发起取消请求 4. 取消时至少赋值一个信息,reason通常应该赋值分析取消码,可使用
CancelCodes中的工具方法。 -
isCancelRequested
default boolean isCancelRequested()是否已收到取消信号 任务的执行者将持有该令牌,在调度任务前会检测取消信号;如果任务已经开始,则由用户的任务自身检测取消和中断信号。 -
reason
default int reason()取消的原因 (1~10为底层使用,10以上为用户自定义)T -
checkCancel
default void checkCancel()检测取消信号 如果收到取消信号,则抛出CancellationException -
thenAccept
添加的action将在Token收到取消信号时执行 1.如果已收到取消请求,则给定的action会立即执行。 2.如果尚未收到取消请求,则给定action会在收到请求时执行。 -
thenAccept
-
thenAcceptAsync
-
thenAcceptAsync
IRegistration thenAcceptAsync(Executor executor, Consumer<? super ICancelToken> action, int options) -
thenAccept
添加的action将在Token收到取消信号时执行 1.如果已收到取消请求,则给定的action会立即执行。 2.如果尚未收到取消请求,则给定action会在收到请求时执行。 3.如果不期望检测ctx中潜在的取消信号,可通过TaskOptions.STAGE_UNCANCELLABLE_CTX关闭。- 参数:
action- 回调任务ctx- 上下文options- 调度选项- 返回:
- 取消句柄
-
thenAccept
-
thenAcceptAsync
IRegistration thenAcceptAsync(Executor executor, BiConsumer<? super ICancelToken, Object> action, Object ctx) -
thenAcceptAsync
IRegistration thenAcceptAsync(Executor executor, BiConsumer<? super ICancelToken, Object> action, Object ctx, int options) -
thenRun
-
thenRun
-
thenRunAsync
-
thenRunAsync
-
thenRun
-
thenRun
-
thenRunAsync
-
thenRunAsync
-
thenNotify
添加一个特定类型的监听器 (用于特殊需求时避免额外的闭包 - task经常需要监听取消令牌) -
thenNotify
-
thenNotifyAsync
-
thenNotifyAsync
IRegistration thenNotifyAsync(Executor executor, ICancelTokenListener action, Object ctx, int options) -
thenTransferTo
该接口用于方便构建子上下文 1.子token会在当前token进入取消状态时被取消 2.该接口本质是一个快捷方法,但允许子类优化注意:在Future体系下,child是上游任务;而在行为树这类体系下,child是下游任务。
- 参数:
child- 接收结果的子tokenoptions- 调度选项
-
thenTransferTo
-
thenTransferToAsync
-
thenTransferToAsync
-