Futuro completable con tiempo de espera no funciona

En lugar de

acceptEither(timeoutAfter(50, TimeUnit.MILLISECONDS), inPutItemGroup))

necesitarías

applyToEither(timeoutAfter(50, TimeUnit.MILLISECONDS), x -> inPutItemGroup)

para compilar el código. "Aceptar" es una acción que consume un valor sin devolver un nuevo valor, "aplicar" es una acción que produce un nuevo valor.

Sin embargo, todavía hay un error lógico. El futuro devuelto por timeoutAfterse completará excepcionalmente , por lo que las etapas dependientes también se completarán excepcionalmente, sin evaluar funciones, por lo que este método de encadenamiento no es adecuado para reemplazar una excepción con un valor predeterminado.

Peor aún, arreglar esto crearía un nuevo futuro que se completaría con cualquiera de las fuentes futuras, pero eso no afectaría la result.add(itemGroup)acción realizada en una de las fuentes futuras . En su código, el futuro resultante solo se usa para esperar la finalización, pero no para evaluar el resultado. Por lo tanto, cuando transcurra el tiempo de espera, dejará de esperar a que se complete, mientras que aún podría haber subprocesos de fondo que modifiquen la lista.

La lógica correcta es separar los pasos para obtener el valor, que puede ser reemplazado por un valor predeterminado en el tiempo de espera, y el paso de agregar el resultado, ya sea el valor obtenido o el valor predeterminado, a la lista de resultados. Luego, puede esperar la finalización de todas las addacciones. En un tiempo de espera, puede haber getUpdatedItemGroupevaluaciones en curso (no hay forma de detener su ejecución), pero su resultado sería ignorado, por lo que no afecta la lista de resultados.

También vale la pena señalar que crear un nuevo ScheduledExecutorServiceelemento para cada elemento de la lista (que no se cierra después del uso, para empeorar las cosas), no es el enfoque correcto.

// 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;
}

Aquí, el supplyAsyncproduce un CompletableFutureque proporcionará el resultado de la getUpdatedItemGroupevaluación. La timeoutAfterinvocación programará una finalización con un valor predeterminado después del tiempo de espera, sin crear un nuevo futuro, luego, la acción dependiente encadenada thenAcceptagregará el valor del resultado a la resultlista.

Tenga en cuenta que a synchronizedListpermite agregar elementos de varios subprocesos, pero agregar desde múltiples subprocesos dará como resultado un orden impredecible, no relacionado con el orden de la lista de origen.

Respuesta 1

Necesita serializar objetos Java a JSON mientras realiza la compresión, como cambio de nombre, exclusión, etc. Los objetos usan la clase de jar, cuyo código fuente no está disponible. Miré a través de muchas bibliotecas (...

Necesito ayuda real con mi proyecto Java. Es un JFrame controlado por la consola, donde los comandos que escribe en la consola DEBEN reaccionar a la ventana JFrame, solo que no lo hace. Este es un gran problema. Aquí'...

Digamos que tenía una JMenuBar. En ese JMenuBar, tuve un JMenu. En ese JMenu, había otro menú, y en ese menú, había elementos. ¿Hay alguna forma de hacer esto?

Estoy usando archivos mapeados de memoria en algún código Java para escribir rápidamente en un archivo 2G. Estoy mapeando todo el archivo en la memoria. El problema que tengo con mi solución es que si el archivo en el que estoy escribiendo ...