java - Java 并发实践“清单 7.21. ExecutorService 在关机后跟踪取消的任务。”。比赛条件在哪里?
问题描述
我正在阅读Java Concurrency in Practice并遇到以下代码片段。
public class TrackingExecutor extends AbstractExecutorService {
private final ExecutorService exec;
private final Set<Runnable> tasksCancelledAtShutdown =
Collections.synchronizedSet(new HashSet<Runnable>());
...
public List<Runnable> getCancelledTasks() {
if (!exec.isTerminated())
throw new IllegalStateException(...);
return new ArrayList<Runnable>(tasksCancelledAtShutdown);
}
public void execute(final Runnable runnable) {
exec.execute(new Runnable() {
public void run() {
try {
runnable.run();
} finally {
if (isShutdown()
&& Thread.currentThread().isInterrupted())
tasksCancelledAtShutdown.add(runnable);
}
}
});
}
// delegate other ExecutorService methods to exec
}
书上说:
TrackingExecutor 有一个不可避免的竞争条件,可能会导致误报:被标识为已取消但实际上已完成的任务。这是因为线程池可能在任务的最后一条指令执行和池将任务记录为完成之间关闭。
是指下面的情况吗?
- 一个工作线程已完成,但在块
runnable.run()
处停止。finally
exec
已关闭。- 工作线程执行
finally
块并添加runnable
到tasksCancelledAtShutdown
. (runnable.run()
已完结,应该认作finished
,不是cancelledAtShutdown
。)
我做对了吗?如果不是,竞争条件在哪里?“线程池可以在任务的最后一条指令执行和池将任务记录为完成之间关闭”的真正含义是什么?
解决方案
推荐阅读
- python - db.create_all() 'NoneType' 对象没有属性 'drivername'
- php - 其他文件夹中的 file_get_contents
- phpstorm - 声明自动完成的变量类型
- reactjs - 如何为新更新的道具值重新渲染子组件
- algorithm - DNA子序列动态规划问题
- c# - 用组合框列交换 DataGrid 中的项目?
- node.js - 如何使用 NodeJS 在 GCP 中已创建/现有的 VM 中运行 bash 脚本?
- r-markdown - 是否可以在不同的 rMarkdown 模板之间共享块
- c++ - 初始化静态字段
- python - 提高 lmfit 中多个数据集拟合的速度?字符串调用限制