【问题标题】:What is a common idiom for closing AsynchronousFileChannel?关闭 AsynchronousFileChannel 的常用习语是什么?
【发布时间】:2022-01-30 00:21:11
【问题描述】:

我刚刚发现下面的代码没有按预期工作。

try (AsynchronousFileChannel channel = open(path)) {
    channel.read(, , ,
                 new CompletionHandler() {
                         @Override
                         public void completed(Integer result, Long attachment) {
                         }
                         @Override
                         public void failed(Throwable exc, Long attachment) {
                             // channel already has been closed!!!
                         }
                 });
}

因为AsynchronousFileChannel#read 方法会立即返回,而CompletionHandler 只是无法工作。

任务完成后关闭频道的常用成语是什么?

我应该这样做吗?

AsynchronousFileChannel channel = open(path);

channel.read(, , ,
             new CompletionHandler() {
                     @Override
                     public void completed(Integer result, Long attachment) {
                     }
                     @Override
                     public void failed(Throwable exc, Long attachment) {
                     }
             });

channel.close();

【问题讨论】:

    标签: java asynchronous asynchronousfilechannel


    【解决方案1】:

    希望有人知道一种正确的方法来确保所有正在进行的AsynchronousFileChannel 回调都已完成 - 我找不到合适的 API 调用来结束带有回调的读取操作。在测试中,我注意到CompletionHandler 回调可能会在我的方法调用返回数据读取给它的调用者之后被调用,很好地是在离开下面的资源块的尝试之后关闭AsynchronousFileChannel

    try (AsynchronousFileChannel fc = AsynchronousFileChannel.open(p, StandardOpenOption.READ)) {
        var handler = new CompletionHandler<Integer,Long>() {
            public void completed(Integer result, Long position) {
                // ...
            }
            public void failed(Throwable exc, Long position) {
                // ...
            }
        };
        // Run some reads:
        fc.read(aByteBuffer, startPos, Long.valueOf(startPos), handler);
    }
    return blah; 
    // "handler" still can receive callbacks after this point!
    

    相反,我在方法中使用了CountDownLatch 的变通方法,以便在所有fc.read 调用与CompletionHandler completed / failed 的相应回调匹配之前,try-catch 块不会退出。

    try (AsynchronousFileChannel fc = AsynchronousFileChannel.open(p, StandardOpenOption.READ)) {
    
        // Work out how many fc.read calls you plan to do
        int numberOfReads = 1;
        CountDownLatch countdown = new CountDownLatch(numberOfReads);
    
        var handler = new CompletionHandler<Integer,Long>() {
            public void completed(Integer result, Long position) {
                // ...
                countdown.countDown();
            }
            public void failed(Throwable exc, Long position) {
                // ...
                countdown.countDown();
            }
        };
    
        // Kick off numberOfReads x fc.read
        fc.read(yourByteBuffer, startPos, Long.valueOf(startPos), handler);
    
        // Without next line the AsynchronousFileChannel may continue to run after return
        countdown.await();
    }
    return blah; 
    // No more "handler" callbacks after this point
    

    这不是一个理想的解决方案,因为它依赖于在创建 CountDownLatch 之前计算读取次数。相反,您可以考虑使用动态计数器或使用非回调读取方法:Future&lt;Integer&gt; fut = read(ByteBuffer, long) 样式并在调用者线程中调用 fut.get();

    【讨论】:

      猜你喜欢
      • 2016-10-16
      • 2011-02-06
      • 1970-01-01
      • 2020-12-19
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多