Java 什么';这是取消已经运行的CompletableFutures的预期模式

Java 什么';这是取消已经运行的CompletableFutures的预期模式,java,completable-future,Java,Completable Future,我在“Java8在运行”中找不到任何关于为什么CompletableFuture故意忽略MayInterruptfRunning的信息。但即使如此,我也看不到定制cancel(boolean)的任何钩子,这在中断不影响阻塞操作(如I/O流、简单锁等)的情况下非常有用。到目前为止,任务本身似乎是预期的挂钩,在未来的抽象层上工作根本没有任何好处 因此,我要问的是,为了从这种情况中挤出一些neet自定义取消机制,必须引入的最小样板代码集。您可以想象一个可完成的未来只是异步子流程的一个(键入的)句柄(当

我在“Java8在运行”中找不到任何关于为什么
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做出正确反应。

a
CompletableFuture
是封装以下三种状态之一的对象:

  • 没有完成
  • 以值完成,或
  • 破例完成
  • 从“未完成”到其他状态之一的转换可由传递到其工厂方法之一或
    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