Java ForkJoinPool重置线程中断状态
我只是在取消由返回的未来时注意到以下现象。给出以下示例代码:Java ForkJoinPool重置线程中断状态,java,multithreading,java.util.concurrent,forkjoinpool,Java,Multithreading,Java.util.concurrent,Forkjoinpool,我只是在取消由返回的未来时注意到以下现象。给出以下示例代码: ForkJoinPool pool = new ForkJoinPool(); Future<?> fut = pool.submit(new Callable<Void>() { @Override public Void call() throws Exception { while (true) { if (Thread.currentThread().isInterrupt
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);
ForkJoinPool-pool=新的ForkJoinPool();
Future fut=pool.submit(新的可调用(){
@凌驾
public Void call()引发异常{
while(true){
如果(Thread.currentThread().isInterrupted()){/发生这种情况是因为Future
是一个ForkJoinTask.AdaptedCallable
扩展了ForkJoinTask
,其取消方法是:
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;
}
}
}
public boolean cancel(boolean可能中断frunning){
返回设置完成(取消)=取消;
}
私有整数集完成(整数完成){
对于(int s;;){
如果((s=状态)<0)
返回s;
如果(不安全。比较数据(此、状态偏移、s、完成)){
如果(s!=0)
已同步(此){notifyAll();}
返回完成;
}
}
}
它不做任何中断,只是设置状态。我想这是因为ForkJoinPools
的未来可能有一个非常复杂的树结构,并且不清楚取消它们的顺序。在@Mkhail答案上分享更多信息:
使用ForkJoinPool execute()而不是submit()将强制失败的Runnable抛出工作异常,此异常将被线程UncaughtExceptionHandler捕获
摘自Java 8代码:
提交正在使用AdaptedRunnableAction()。
execute正在使用RunnableExecuteAction()(请参阅重试(ex))
/**
*无结果的可运行适配器
*/
静态最终类AdaptedRunnableAction扩展了ForkJoinTask
实现可运行未来{
最终可运行;
AdaptedRunnableAction(可运行可运行){
如果(runnable==null)抛出新的NullPointerException();
this.runnable=runnable;
}
public final Void getRawResult(){return null;}
公开最终作废setRawResult(作废v){}
public final boolean exec(){runnable.run();返回true;}
公共最终无效运行(){invoke();}
私有静态最终长serialVersionUID=52324539592276885070L;
}
/**
*用于可运行的适配器,在该适配器中,故障强制工作异常
*/
静态最终类RunnableExecuteAction扩展了ForkJoinTask{
最终可运行;
RunnableExecuteAction(Runnable-Runnable){
如果(runnable==null)抛出新的NullPointerException();
this.runnable=runnable;
}
public final Void getRawResult(){return null;}
公开最终作废setRawResult(作废v){}
public final boolean exec(){runnable.run();返回true;}
无效异常(可丢弃的ex){
rethrow(ex);//在exec()捕获之外重试。
}
私有静态最终长serialVersionUID=52324539592276885070L;
}
BTW,为什么要在这个案例中使用FJP?@Mikhail这只是我们用例的一个非常小的示例。我们在可调用函数中启动了一些递归操作,这些操作在ForkJoinTask.getPool()上被调用感谢Mikhail的调查。看起来无法从Callable中检查取消。我需要提交一个ForkJoinTask并调用isCancelled(),这很糟糕,因为您总是需要传递对ForkJoinTask的引用来检查取消
/**
* 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;
}