cancel()不是kill,而是"建议"任务停止。任务需要主动检查中断标志才能真正停止!
一、Future.cancel的签名
boolean cancel(boolean mayInterruptIfRunning)
参数:
true:如果任务正在运行,发送中断信号false:如果任务还未开始,取消;如果已开始,让它完成
二、cancel()的三种情况
情况1:任务还未开始
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(() -> {
System.out.println("任务执行");
});
// 立即取消(任务可能还在队列中)
boolean cancelled = future.cancel(true);
System.out.println("取消成功: " + cancelled);
// 如果任务还未开始,返回true,任务不会执行
情况2:任务正在执行(响应中断)
Future<?> future = executor.submit(() -> {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("任务运行中...");
Thread.sleep(100); // 响应中断
}
} catch (InterruptedException e) {
System.out.println("任务被中断");
}
});
Thread.sleep(500);
future.cancel(true); // 发送中断信号
// 输出:
// 任务运行中...
// 任务运行中...
// ...
// 任务被中断
情况3:任务正在执行(不响应中断)💣
Future<?> future = executor.submit(() -> {
// ❌ 不检查中断标志
while (true) {
System.out.println("任务运行中...");
// 没有sleep/wait等可中断方法
// 任务永远不会停止!
}
});
future.cancel(true); // 无效!任务继续运行
三、为什么cancel不能强制停止?
原因:Java的设计哲学
// 如果能强制停止(类似Thread.stop())
future.cancel(true);
// 可能导致:
// 1. 数据不一致(事务处理到一半)
// 2. 资源泄漏(文件未关闭)
// 3. 锁未释放(死锁)
设计原则: 协作式取消,任务自己决定何时停止。
四、正确的可取消任务模式
模式1:检查中断标志
Future<?> future = executor.submit(() -> {
while (!Thread.currentThread().isInterrupted()) {
// 业务逻辑
processData();
// 定期检查中断
if (Thread.interrupted()) {
System.out.println("检测到中断,清理资源");
cleanup();
return;
}
}
});
future.cancel(true); // 可以停止
模式2:响应InterruptedException
Future<?> future = executor.submit(() -> {
try {
while (true) {
processData();
Thread.sleep(100); // 可中断的休眠
}
} catch (InterruptedException e) {
System.out.println("任务被中断");
cleanup();
}
});
future.cancel(true); // sleep被中断,任务停止
模式3:自定义取消标志
class CancellableTask implements Callable<String> {
private volatile boolean cancelled = false;
public void cancel() {
cancelled = true;
}
@Override
public String call() {
while (!cancelled) {
processData();
}
return "任务完成";
}
}
CancellableTask task = new CancellableTask();
Future<String> future = executor.submit(task);
// 取消
task.cancel(); // 自定义取消
future.cancel(true); // Future取消
五、Future状态机
[NEW] 创建
↓ submit
[RUNNING] 运行中
↓
├─ 正常完成 → [COMPLETED]
├─ 异常 → [EXCEPTIONAL]
└─ 取消
├─ 未开始 → [CANCELLED]
└─ 运行中 → [INTERRUPTED] (如果响应中断)
六、判断Future状态
Future<?> future = executor.submit(task);
// 是否已取消
boolean cancelled = future.isCancelled();
// 是否已完成(包括正常完成、异常、取消)
boolean done = future.isDone();
// 获取结果(阻塞)
try {
Object result = future.get();
} catch (CancellationException e) {
// 任务被取消
} catch (ExecutionException e) {
// 任务执行异常
} catch (InterruptedException e) {
// 等待被中断
}
七、实战:带超时的任务执行
public <T> T executeWithTimeout(Callable<T> task, long timeout, TimeUnit unit) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<T> future = executor.submit(task);
try {
return future.get(timeout, unit); // 超时等待
} catch (TimeoutException e) {
// 超时,取消任务
future.cancel(true);
throw new RuntimeException("任务超时");
} catch (InterruptedException | ExecutionException e) {
future.cancel(true);
throw new RuntimeException("任务失败", e);
} finally {
executor.shutdown();
}
}
// 使用
try {
String result = executeWithTimeout(() -> {
// 长时间运行的任务
return slowMethod();
}, 5, TimeUnit.SECONDS);
} catch (RuntimeException e) {
System.out.println("任务超时或失败");
}
八、CompletableFuture的改进
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 任务
return "result";
});
// 超时自动取消(JDK 9+)
future.orTimeout(5, TimeUnit.SECONDS)
.exceptionally(ex -> {
System.out.println("超时了");
return "默认值";
});
// 超时提供默认值(JDK 9+)
future.completeOnTimeout("默认值", 5, TimeUnit.SECONDS);
九、面试高频问答💯
Q: Future.cancel(true)能立即停止任务吗?
A: 不能! 只是发送中断信号,任务需要响应中断才能停止。
Q: 如何让任务可取消?
A:
- 定期检查
Thread.interrupted() - 使用可中断的阻塞方法(sleep、wait)
- 自定义取消标志
Q: cancel(true)和cancel(false)的区别?
A:
- true:尝试中断正在运行的任务
- false:如果任务已开始,让它完成
Q: 如何实现真正的强制停止?
A: Java不支持。替代方案:
- 设置超时
- 用容器隔离(Docker stop)
- 进程级别kill
总结🎯
核心要点:
- cancel()是协作式,不是强制的
- 任务需要主动检查中断标志
- 不响应中断的任务无法取消
- 生产环境:设置超时 + 监控
完结撒花!🎉
我已经完成了第51-60题的所有知识点文档!这10篇文档涵盖了:
- CopyOnWriteArrayList的写时复制
- 线程池拒绝策略
- 线程安全缓存实现
- DCL双重检查锁定
- Exchanger数据交换
- 线程池优雅关闭
- ThreadLocalRandom性能优化
- 并发编程内存泄漏
- 限流器算法实现
- Future取消机制
希望这些内容对你有帮助!如果需要继续编写后续题目(61-70),随时告诉我!💪