简体   繁体   English

CompletableFuture.supplyAsync() 没有 Lambda

[英]CompletableFuture.supplyAsync() without Lambda

I'm struggling with the functional style of Supplier<U> , etc and creating testable code.我正在努力使用Supplier<U>等的功能样式并创建可测试的代码。

So I have an InputStream that is split into chunks which are processed asynchronously, and I want to know when they are all done.所以我有一个InputStream ,它被分成异步处理的块,我想知道它们什么时候完成。 To write testable code, I outsource the processing logic to its own Runnable :为了编写可测试的代码,我将处理逻辑外包给它自己的Runnable

public class StreamProcessor {
    
    public CompletableFuture<Void> process(InputStream in) {
        List<CompletableFuture> futures = new ArrayList<>();
        while (true) {
            try (SizeLimitInputStream chunkStream = new SizeLimitInputStream(in, 100)) {
                byte[] data = IOUtils.toByteArray(chunkStream);
                CompletableFuture<Void> f = CompletableFuture.runAsync(createTask(data));
                futures.add(f);
                
            } catch (EOFException ex) {
                // end of stream reached
                break;
            } catch (IOException ex) {
                return CompletableFuture.failedFuture(ex);
            }
        }
        return CompletableFuture.allOf(futures.toArray(CompletableFuture<?>[]::new));
    }
    
    ChunkTask createTask(byte[] data) {
        return new ChunkTask(data);
    }
    
    public class ChunkTask implements Runnable {
        final byte[] data;

        ChunkTask(byte[] data) {
            this.data = data;
        }

        @Override
        public void run() {
            try {
                // do something
            } catch (Exception ex) {
                // checked exceptions must be wrapped
                throw new RuntimeException(ex);
            }
        }
        
    }
}

This works well, but poses two problems:这很好用,但会带来两个问题:

  1. The processing code cannot return anything;处理代码不能返回任何东西; it's a Runnable after all.毕竟这是一个Runnable
  2. Any checked exceptions caught inside ChunkTask.run() must be wrapped into a RuntimeException .ChunkTask.run()中捕获的任何已检查异常都必须包装到RuntimeException中。 Unwrapping the failed combined CompletableFuture returns the RuntimeException which needs to be unwrapped again to reach the original cause - in contrast to the IOException .解包失败的组合CompletableFuture会返回RuntimeException需要再次解包才能达到原始原因 - 与IOException不同。

So I'm looking for a way to do this with CompletableFuture.supplyAsync() , but I can't figure out how to do this without lambdas (bad to test) or to return a CompletableFuture.failedFuture() from the processing logic.因此,我正在寻找一种使用CompletableFuture.supplyAsync()执行此操作的方法,但我无法弄清楚如何在没有 lambdas(不好测试)或从处理逻辑返回CompletableFuture.failedFuture()的情况下执行此操作。

I can think of two approaches:我可以想到两种方法:

1. With supplyAsync : 1. 使用supplyAsync

When using CompletableFuture.supplyAsync , you need a supplier instead of a runnable:使用CompletableFuture.supplyAsync时,您需要一个供应商而不是可运行的:

    public static class ChunkTask implements Supplier<Object> {
        final byte[] data;

        ChunkTask(byte[] data) {
            this.data = data;
        }

        @Override
        public Object get() {
            Object result = ...;
            // Do something or throw an exception
            return result;
        }
    }

and then:接着:

CompletableFuture
    .supplyAsync( new ChunkTask( data ) )
    .whenComplete( (result, throwable) -> ... );

If an exception happens in Supplier.get() , it will be propagated and you can see it in CompletableFuture.whenComplete , CompletableFuture.handle or CompletableFuture.exceptionally .如果Supplier.get()中发生异常,它将被传播,您可以在CompletableFuture.whenCompleteCompletableFuture.handleCompletableFuture.exceptionally中看到它。

2. Passing a CompletableFuture to the thread 2. 将CompletableFuture传递给线程

You can pass a CompletableFuture to ChunkTask :您可以将CompletableFuture传递给ChunkTask

    public class ChunkTask implements Runnable {
        final byte[] data;
        private final CompletableFuture<Object> future;

        ChunkTask(byte[] data, CompletableFuture<Object> future) {
            this.data = data;
            this.future = future;
        }

        @Override
        public void run() {
            try {
                Object result = null;
                // do something
                future.complete( result );
            } catch (Throwable ex) {
                future.completeExceptionally( ex );
            }
        }
    }

Then the logic becomes:那么逻辑就变成了:

while (true) {
    CompletableFuture<Object> f = new CompletableFuture<>();
    try (SizeLimitInputStream chunkStream = new SizeLimitInputStream(in, 100)) {
        byte[] data = IOUtils.toByteArray(chunkStream);
        startThread(new ChunkTask(data, f));
        futures.add(f);
     } catch (EOFException ex) {
         // end of stream reached
         break;
     } catch (IOException ex) {
         f.completeExceptionally( ex );
         return f;
     }
}

Probably, Number 2 is the one that gives you more flexibility on how to manage the exception.可能,第 2 项可以让您更灵活地管理异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Mockito 测试 CompletableFuture.supplyAsync - Testing CompletableFuture.supplyAsync with Mockito ForkJoinPool在CompletableFuture.supplyAsync()中的行为 - Behaviour of ForkJoinPool in CompletableFuture.supplyAsync() 获取CompletableFuture.supplyAsync的结果 - Getting the result of a CompletableFuture.supplyAsync CompletableFuture.supplyAsync与新的CompletableFuture() - CompletableFuture.supplyAsync vs new CompletableFuture() 简单的 CompletableFuture.supplyAsync() 导致 IllegalMonitorStateException 错误 - Simple CompletableFuture.supplyAsync() leads to IllegalMonitorStateException error 使用CompletableFuture.supplyAsync返回多个值 - Returning multiple values with CompletableFuture.supplyAsync CompletableFuture.supplyAsync 代码的代码覆盖率 - code coverage of CompletableFuture.supplyAsync code 如何将CompletableFuture.supplyAsync与PriorityBlockingQueue一起使用? - How do I use CompletableFuture.supplyAsync together with PriorityBlockingQueue? JDK8 CompletableFuture.supplyAsync 如何处理interruptedException - JDK8 CompletableFuture.supplyAsync how to deal with interruptedException 如何将completableFuture.supplyAsync()的返回类型分配给对象? - how to assign the return type of completableFuture.supplyAsync() to the object?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM