Java 什么';这是取消已经运行的CompletableFutures的预期模式
我在“Java8在运行”中找不到任何关于为什么Java 什么';这是取消已经运行的CompletableFutures的预期模式,java,completable-future,Java,Completable Future,我在“Java8在运行”中找不到任何关于为什么CompletableFuture故意忽略MayInterruptfRunning的信息。但即使如此,我也看不到定制cancel(boolean)的任何钩子,这在中断不影响阻塞操作(如I/O流、简单锁等)的情况下非常有用。到目前为止,任务本身似乎是预期的挂钩,在未来的抽象层上工作根本没有任何好处 因此,我要问的是,为了从这种情况中挤出一些neet自定义取消机制,必须引入的最小样板代码集。您可以想象一个可完成的未来只是异步子流程的一个(键入的)句柄(当
CompletableFuture
故意忽略MayInterruptfRunning
的信息。但即使如此,我也看不到定制cancel(boolean)
的任何钩子,这在中断不影响阻塞操作(如I/O流、简单锁等)的情况下非常有用。到目前为止,任务本身似乎是预期的挂钩,在未来的抽象层上工作根本没有任何好处
因此,我要问的是,为了从这种情况中挤出一些neet自定义取消机制,必须引入的最小样板代码集。您可以想象一个可完成的未来
只是异步子流程的一个(键入的)句柄(当然它还有一些好处)。但它不是异步子流程的控制器。您甚至不能直接访问它(或执行它的线程)
为了实现一个abort()
我这样做,扩展了CompletableFuture
:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import x.y.MyEnum;
/**
* Provides an interruptible CompletableFuture implementation for one time usage.
*/
public final class InteruptibleCompletableFuture extends CompletableFuture<MyEnum>
{
/**
* the embedded executor service
*/
private ExecutorService myExecutorService;
/**
* Executes the given supplier asynchronously and returns the future to wait for.
*
* @param aSupplier the supplier to be executed
* @return the CompletableFuture to wait for
*/
public static InteruptibleCompletableFuture execute(Supplier<MyEnum> aSupplier)
{
InteruptibleCompletableFuture result = new InteruptibleCompletableFuture();
result.myExecutorService.submit( () ->
{
try
{
MyEnum res = aSupplier.get();
result.complete( res);
}
catch ( Throwable ex )
{
result.completeExceptionally( ex);
}
});
return result;
}
private InteruptibleCompletableFuture()
{
super();
myExecutorService = Executors.newSingleThreadExecutor();
}
@Override
public boolean complete( MyEnum value)
{
if ( isDone() )
{
// Future already completed
return false;
}
shutdownExecutorService();
return super.complete( value);
}
@Override
public boolean completeExceptionally( Throwable ex)
{
if ( isDone() )
{
// Future already completed
return false;
}
shutdownExecutorService();
return super.completeExceptionally( ex);
}
private void shutdownExecutorService()
{
try
{
myExecutorService.shutdownNow();
}
catch ( Throwable e )
{
// log error
}
}
}
import java.util.concurrent.CompletableFuture;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.function.Supplier;
导入x.y.MyEnum;
/**
*为一次性使用提供可中断、可完成的未来实现。
*/
公共最终类InteruptableCompletableFuture扩展CompletableFuture
{
/**
*嵌入式执行器服务
*/
私人执行者服务myExecutorService;
/**
*异步执行给定的供应商并返回要等待的未来。
*
*@param aSupplier待执行的供应商
*@返回可完成的未来等待
*/
公共静态中断可完成未来执行(供应商和供应商)
{
InteruptableCompletableFuture结果=新建InteruptableCompletableFuture();
结果.myExecutorService.submit(()->
{
尝试
{
MyEnum res=aSupplier.get();
结果:完成(res);
}
捕获(可丢弃的ex)
{
结果:异常完全(ex);
}
});
返回结果;
}
私有InteruptableCompletableFuture()
{
超级();
myExecutorService=Executors.newSingleThreadExecutor();
}
@凌驾
公共布尔值完成(MyEnum值)
{
if(isDone())
{
//未来计划已经完成
返回false;
}
关闭ExecutorService();
返回super.complete(值);
}
@凌驾
公共布尔完备性异常(Throwable ex)
{
if(isDone())
{
//未来计划已经完成
返回false;
}
关闭ExecutorService();
异常返回超级完整(ex);
}
私有void shutdownExecutorService()
{
尝试
{
myExecutorService.shutdownNow();
}
捕获(可丢弃的e)
{
//日志错误
}
}
}
这个想法是,这个实现对执行者有影响。强制从主应用程序委托终止调用myExecutorService.shutdownNow()
。仔细阅读此方法的javadoc
请注意,java没有合法的方法杀死线程。调用myThread.interrupt()不会终止它。如果线程正在监视器中等待(抛出InterruptedException),它只是设置interrupted标志并唤醒线程。如果在循环中执行批处理作业,您的实现必须定期检查interrupted标志,并对InterruptedException做出正确反应。aCompletableFuture
是封装以下三种状态之一的对象:
没有完成
以值完成,或
破例完成
从“未完成”到其他状态之一的转换可由传递到其工厂方法之一或CompletionStage
实现方法之一的函数触发
但是,也可以在其上调用complete
或complete。在这方面,对其调用cancel
与对其调用completeeexception(new CancellationException())
具有相同的效果
这也是它的类名所暗示的,它是一个可以完成的未来,而不是(最终)将要完成的未来。该类不提供对可能在任意线程中运行的现有完成尝试的控制,也不专门处理自己安排的完成尝试
同样重要的是要理解,当通过CompletionStage
实现方法链接操作时,生成的未来只代表链的最后一个阶段,取消它也只能影响最后一个阶段
例如,以下代码
CompletableFuture cf=CompletableFuture.supplyAsync(()->{
锁支持。Parknos(时间单位。秒。toNanos(1));
字符串s=“value1”;
System.out.println(“返回首字母”+s);
返回s;
})。然后应用(s->{
锁支持。Parknos(时间单位。秒。toNanos(1));
s=s.toUpperCase();
System.out.println(“返回转换”+s);
返回s;
}).然后接受(s->{
System.out.println(“开始最后阶段”);
锁支持。Parknos(时间单位。秒。toNanos(1));
系统输出打印项次(“已处理”+s);
});
cf.cancel(假);
ForkJoinPool.commonPool()等待静止(1,TimeUnit.DAYS);
将打印
返回初始值1
返回转换后的值1
证明只有链的最后一个阶段被取消,而之前的st