我刚刚注意到,当取消ForkJoinPool返回的未来时,会出现以下现象。给出以下示例代码:
ForkJoinPool pool = new ForkJoinPool();
Future<?> fut = pool.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
while (true) {
if (Thread.currentThread().isInterrupted()) { // <-- never true
System.out.println("interrupted");
throw new InterruptedException();
}
}
}
});
Thread.sleep(1000);
System.out.println("cancel");
fut.cancel(true);这个程序从不打印interrupted。ForkJoinTask#cancel(布尔型)的博士们说:
mayInterruptIfRunning -此值在默认实现中不起作用,因为中断不用于控制取消。
如果ForkJoinTasks忽略中断,您还应该如何检查提交给ForkJoinPool的调用中是否取消?
发布于 2014-01-24 06:49:21
这是因为Future<?>是一个扩展ForkJoinTask的ForkJoinTask.AdaptedCallable,其cancel方法是:
public boolean cancel(boolean mayInterruptIfRunning) {
return setCompletion(CANCELLED) == CANCELLED;
}
private int setCompletion(int completion) {
for (int s;;) {
if ((s = status) < 0)
return s;
if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {
if (s != 0)
synchronized (this) { notifyAll(); }
return completion;
}
}
}它不做任何中断,它只是设置状态。我认为这种情况的发生是因为ForkJoinPools的Future可能有一个非常复杂的树结构,并且不清楚取消它们的顺序。
发布于 2018-05-13 16:53:11
在@Mkhail的回答上分享更多的光线:
使用ForkJoinPool execute()而不是submit()将强制一个失败的Runnable抛出一个工作异常,而这个异常将被线程UncaughtExceptionHandler捕获。
取自Java 8代码:
submit使用AdaptedRunnableAction()。
execute使用RunnableExecuteAction() (参见重新抛出(Ex))。
/**
* Adaptor for Runnables without results
*/
static final class AdaptedRunnableAction extends ForkJoinTask<Void>
implements RunnableFuture<Void> {
final Runnable runnable;
AdaptedRunnableAction(Runnable runnable) {
if (runnable == null) throw new NullPointerException();
this.runnable = runnable;
}
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) { }
public final boolean exec() { runnable.run(); return true; }
public final void run() { invoke(); }
private static final long serialVersionUID = 5232453952276885070L;
}
/**
* Adaptor for Runnables in which failure forces worker exception
*/
static final class RunnableExecuteAction extends ForkJoinTask<Void> {
final Runnable runnable;
RunnableExecuteAction(Runnable runnable) {
if (runnable == null) throw new NullPointerException();
this.runnable = runnable;
}
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) { }
public final boolean exec() { runnable.run(); return true; }
void internalPropagateException(Throwable ex) {
rethrow(ex); // rethrow outside exec() catches.
}
private static final long serialVersionUID = 5232453952276885070L;
}https://stackoverflow.com/questions/21320156
复制相似问题