Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 超时不工作的可完成未来_Java_Multithreading_Java 8_Executorservice_Completable Future - Fatal编程技术网

Java 超时不工作的可完成未来

Java 超时不工作的可完成未来,java,multithreading,java-8,executorservice,completable-future,Java,Multithreading,Java 8,Executorservice,Completable Future,我是一个新的完整的未来。我试图为元素列表(即参数)调用一个并行方法,然后组合结果以创建最终响应。我还试图设置50毫秒的超时时间,这样,如果50毫秒内呼叫没有返回,我将返回一个默认值 到目前为止,我已经尝试过: { List<ItemGroup> result = Collections.synchronizedList(Lists.newArrayList()); try { List<CompletableFuture> comp

我是一个新的完整的未来。我试图为元素列表(即参数)调用一个并行方法,然后组合结果以创建最终响应。我还试图设置50毫秒的超时时间,这样,如果50毫秒内呼叫没有返回,我将返回一个默认值

到目前为止,我已经尝试过:

    {

     List<ItemGroup> result = Collections.synchronizedList(Lists.newArrayList());

    try {
     List<CompletableFuture> completableFutures = response.getItemGroupList().stream()
     .map(inPutItemGroup -> 
       CompletableFuture.runAsync(() -> {
           final ItemGroup itemGroup = getUpdatedItemGroup(inPutItemGroup);               //call which I am tryin to make parallel

           // this is thread safe
           if (null != itemGroup) {
                  result.add(itemGroup); //output of the call
           }
        }, executorService).acceptEither(timeoutAfter(50, TimeUnit.MILLISECONDS),inPutItemGroup))  //this line throws error     
     .collect(Collectors.toList());

// this will wait till all threads are completed
    CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[completableFutures.size()]))
                        .join();
} catch (final Throwable t) {
     final String errorMsg = String.format("Exception occurred while rexecuting parallel call");
                log.error(errorMsg, e);
                result = response.getItemGroupList(); //default value - return the input value if error
    }

    Response finalResponse = Response.builder()
                    .itemGroupList(result)
                    .build();

    }

     private <T> CompletableFuture<T> timeoutAfter(final long timeout, final TimeUnit unit) {
            CompletableFuture<T> result = new CompletableFuture<T>();

            //Threadpool with 1 thread for scheduling a future that completes after a timeout
            ScheduledExecutorService delayer = Executors.newScheduledThreadPool(1);
            String message = String.format("Process timed out after %s %s", timeout, unit.name().toLowerCase());
            delayer.schedule(() -> result.completeExceptionally(new TimeoutException(message)), timeout, unit);
            return result;
     }
{
列表结果=Collections.synchronizedList(Lists.newArrayList());
试一试{
List completableFutures=response.getItemGroupList().stream()
.map(inPutItemGroup->
CompletableFuture.runAsync(()->{
final ItemGroup ItemGroup=getUpdatedItemGroup(inPutItemGroup);//我正在尝试并行调用的调用
//这是线程安全的
if(null!=itemGroup){
result.add(itemGroup);//调用的输出
}
}acceptor(timeoutAfter(50,TimeUnit.ms),inPutItemGroup))//此行抛出错误
.collect(Collectors.toList());
//这将等待所有线程完成
CompletableFuture.allOf(completableFutures.toArray(新的completableFutures[completableFutures.size()]))
.join();
}捕获(最终可丢弃的t){
final String errorMsg=String.format(“在重新执行并行调用时发生异常”);
日志错误(errorMsg,e);
result=response.getItemGroupList();//默认值-如果出现错误,则返回输入值
}
Response finalResponse=Response.builder()
.itemGroupList(结果)
.build();
}
专用CompletableFuture timeoutAfter(最终长超时,最终时间单位){
CompletableFuture结果=新建CompletableFuture();
//具有1个线程的线程池,用于调度超时后完成的未来
ScheduledExecutorService delayer=执行者。newScheduledThreadPool(1);
String message=String.format(“进程在%s%s之后超时”,超时,unit.name().toLowerCase());
delayer.schedule(()->result.completeException(新的TimeoutException(消息)),超时,单位);
返回结果;
}
但我一直在说:

 error: incompatible types: ItemGroup cannot be converted to Consumer<? super Void>
    [javac]                             itemGroup))

incompatible types: inference variable T has incompatible bounds
    [javac]                     .collect(Collectors.toList());
    [javac]                             ^
    [javac]     equality constraints: CompletableFuture
    [javac]     lower bounds: Object
    [javac]   where T is a type-variable:

错误:不兼容类型:无法将ItemGroup转换为Consumer接受的签名如下所示:

public CompletableFuture<Void> acceptEither(
    CompletionStage<? extends T> other, 
    Consumer<? super T> action
) {
.acceptEither(
     timeoutAfter(50, TimeUnit.MILLISECONDS),
     inPutItemGroup
)
因此,您看到您尝试将
ItemGroup
作为
Consumer而不是

acceptEither(timeoutAfter(50, TimeUnit.MILLISECONDS), inPutItemGroup))
你需要

applyToEither(timeoutAfter(50, TimeUnit.MILLISECONDS), x -> inPutItemGroup)
编译代码。“接受”是使用值而不返回新值的操作,“应用”是生成新值的操作

但是,仍然存在一个逻辑错误。
timeoutAfter
返回的未来将异常完成,因此相关阶段也将异常完成,而不评估函数,因此此链接方法不适合用默认值替换异常

更糟糕的是,修复此问题将创建一个新的未来,该未来将由任一源未来完成,但这不会影响在其中一个源未来中执行的
结果。添加(itemGroup)
操作。在代码中,生成的未来只用于等待完成,而不用于评估结果。因此,当超时时间过去时,您将停止等待完成,而仍然可能有后台线程修改列表

正确的逻辑是将获取值(超时时会被默认值取代)的步骤与将结果(获取的值或默认值)添加到结果列表的步骤分开。然后,您可以等待所有
add
操作的完成。超时时,可能仍在进行
getUpdatedItemGroup
求值(无法停止其执行),但其结果将被忽略,因此不会影响结果列表

还值得指出的是,为每个列表元素创建一个新的
ScheduledExecutorService
(使用后不会关闭,更糟的是),这不是正确的方法

// result must be effectively final
List<ItemGroup> result = Collections.synchronizedList(new ArrayList<>());
List<ItemGroup> endResult = result;
ScheduledExecutorService delayer = Executors.newScheduledThreadPool(1);
try {
    CompletableFuture<?>[] completableFutures = response.getItemGroupList().stream()
    .map(inPutItemGroup ->
        timeoutAfter(delayer, 50, TimeUnit.MILLISECONDS,
            CompletableFuture.supplyAsync(
                () -> getUpdatedItemGroup(inPutItemGroup), executorService),
            inPutItemGroup)
         .thenAccept(itemGroup -> {
            // this is thread safe, but questionable,
            // e.g. the result list order is not maintained
            if(null != itemGroup) result.add(itemGroup);
         })
    )
    .toArray(CompletableFuture<?>[]::new);

    // this will wait till all threads are completed
    CompletableFuture.allOf(completableFutures).join();
} catch(final Throwable t) {
    String errorMsg = String.format("Exception occurred while executing parallel call");
    log.error(errorMsg, e);
    endResult = response.getItemGroupList();
}
finally {
    delayer.shutdown();
}

Response finalResponse = Response.builder()
    .itemGroupList(endResult)
    .build();
//结果必须是最终的
列表结果=Collections.synchronizedList(新的ArrayList());
List endResult=结果;
ScheduledExecutorService delayer=执行者。newScheduledThreadPool(1);
试一试{
CompletableFuture[]completableFutures=response.getItemGroupList().stream()
.map(inPutItemGroup->
timeoutAfter(延迟器,50,TimeUnit.ms,
CompletableFuture.SupplySync(
()->getUpdatedItemGroup(inPutItemGroup),executorService),
输入项组)
.然后接受(项目组->{
//这是线程安全的,但值得怀疑,
//例如,不维护结果列表顺序
if(null!=itemGroup)result.add(itemGroup);
})
)
.toArray(可完成的未来[]::新);
//这将等待所有线程完成
CompletableFuture.allOf(completableFutures.join();
}捕获(最终可丢弃的t){
String errorMsg=String.format(“执行并行调用时发生异常”);
日志错误(errorMsg,e);
endResult=response.getItemGroupList();
}
最后{
delayer.shutdown();
}
Response finalResponse=Response.builder()
.itemGroupList(endResult)
.build();
private CompletableFuture timeoutAfter(ScheduledExecutor服务),
长超时、时间单位、可完成未来f、T值){
es.时间表(()->f.complete(值)、超时、单位);
返回f;
}
这里,
supplyAsync
生成一个
CompletableFuture
,它将提供
getupdatetemgroup
评估的结果。调用
timeoutAfter
将在超时后使用默认值安排完成,而不创建新的未来,然后,通过
thenacept
链接的依赖操作将结果添加到
// result must be effectively final
List<ItemGroup> result = Collections.synchronizedList(new ArrayList<>());
List<ItemGroup> endResult = result;
ScheduledExecutorService delayer = Executors.newScheduledThreadPool(1);
try {
    CompletableFuture<?>[] completableFutures = response.getItemGroupList().stream()
    .map(inPutItemGroup ->
        timeoutAfter(delayer, 50, TimeUnit.MILLISECONDS,
            CompletableFuture.supplyAsync(
                () -> getUpdatedItemGroup(inPutItemGroup), executorService),
            inPutItemGroup)
         .thenAccept(itemGroup -> {
            // this is thread safe, but questionable,
            // e.g. the result list order is not maintained
            if(null != itemGroup) result.add(itemGroup);
         })
    )
    .toArray(CompletableFuture<?>[]::new);

    // this will wait till all threads are completed
    CompletableFuture.allOf(completableFutures).join();
} catch(final Throwable t) {
    String errorMsg = String.format("Exception occurred while executing parallel call");
    log.error(errorMsg, e);
    endResult = response.getItemGroupList();
}
finally {
    delayer.shutdown();
}

Response finalResponse = Response.builder()
    .itemGroupList(endResult)
    .build();
private <T> CompletableFuture<T> timeoutAfter(ScheduledExecutorService es,
    long timeout, TimeUnit unit, CompletableFuture<T> f, T value) {

    es.schedule(() -> f.complete(value), timeout, unit);
    return f;
}