首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ForkJoinPool重置线程中断状态

ForkJoinPool重置线程中断状态
EN

Stack Overflow用户
提问于 2014-01-23 21:55:27
回答 2查看 1.8K关注 0票数 5

我刚刚注意到,当取消ForkJoinPool返回的未来时,会出现以下现象。给出以下示例代码:

代码语言:javascript
复制
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);

这个程序从不打印interruptedForkJoinTask#cancel(布尔型)的博士们说:

mayInterruptIfRunning -此值在默认实现中不起作用,因为中断不用于控制取消。

如果ForkJoinTasks忽略中断,您还应该如何检查提交给ForkJoinPool的调用中是否取消?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-24 06:49:21

这是因为Future<?>是一个扩展ForkJoinTaskForkJoinTask.AdaptedCallable,其cancel方法是:

代码语言:javascript
复制
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;
        }
    }
}

它不做任何中断,它只是设置状态。我认为这种情况的发生是因为ForkJoinPoolsFuture可能有一个非常复杂的树结构,并且不清楚取消它们的顺序。

票数 7
EN

Stack Overflow用户

发布于 2018-05-13 16:53:11

在@Mkhail的回答上分享更多的光线:

使用ForkJoinPool execute()而不是submit()将强制一个失败的Runnable抛出一个工作异常,而这个异常将被线程UncaughtExceptionHandler捕获

取自Java 8代码:

submit使用AdaptedRunnableAction()。

execute使用RunnableExecuteAction() (参见重新抛出(Ex))。

代码语言:javascript
复制
 /**
 * 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;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21320156

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档