0

例如,我想将 100500 字节读入一个数组:

byte[] array = new byte[100500];
int offset = 0;
ByteBuffer buf = ByteBuffer.directBuffer(4096);

channel.read(buffer, null, new LambdaAdapter((count, exception, attachment) -> {
    buf.get(array, offset, count);
    offset += count; //will not work, offset must be final
    if (offset < 100500) {
        channel.read(buffer, null, /*what here? must be lambda we are currently in but we can't use it!*/)
    }
    //here we have our 100500 bytes inside array
});

这里的 LambdaAdapter 是一个简单的包装器,它将 CompletionHandler 转换为具有三个参数的函数式接口。

反正。偏移量可以放在'attachment'参数中,lambda可以预先声明并作为字段重用。然而,生成的代码总是丑陋的丑陋的。

即使对于这样简单的任务,我也无法编写可接受的解决方案 - 对于读取与写入交错并包装在复杂逻辑中的复杂协议,它会是什么样子?

有谁知道处理异步 API 的合适方法?如果您认为 Scala 可以在这里拯救世界,请随意使用它。

4

2 回答 2

1

我知道如何处理一般的异步计算 IO,特别是异步 IO。异步程序应表示为数据流图,如Dataflow_programming中所述。每个节点都有一组输入,每个输入都接受消息或信号,并在所有输入都填满时触发(进入线程池)。例如,代表套接字通道的节点有两个输入:一个用于 ByteBuffers,另一个用于指示该通道是空闲的并且可以接受 IO 请求。因此,节点类似于函数式编程中的函数,但可以重用 - 不会为下一次 IO 操作创建新对象。

Scala(和 Akka)演员不适合,因为每个演员只有一个输入。然而,看看Scala Dataflow - 我还没有学过它,但这个名字很有希望:)。

我已经为 java 的数据流库开发了一个数据流库,但是它的IO 部分有些过时(我在想更优雅,或者至少不那么丑陋的 API)。查看示例子目录中的 echo 服务器实现。

于 2014-06-07T15:59:03.770 回答
0

我找到了可接受的解决方案。首先,以下值得一看:https ://github.com/Netflix/RxJava

至于编码指南...

  • 异步方法是在做任何有用的工作之前返回的方法。
  • 异步操作代码应该从创建新对象开始,我们称之为上下文

    Void startMyAsync(String p1, int p2, Observer callback) {
         return new MyAsyncContext(p1, p2, callback).start();
    }
    
  • 不使用异步操作方法的结果 - 让我们返回 Void 类型。这很有用,因为编译器会检查每个异步方法是否调用另一个异步方法或显式返回 null。

  • 异步方法可以抛出异常
  • 异步回调不应抛出异常 - 必须改用回调错误处理程序
  • 异步回调应该只包含 try...catch 和上下文方法调用。
  • 异步回调也应该返回 Void
  • 不需要 CompletionHandler 提供的其他数据 - 应该使用上下文字段。如果异步流不拆分,则不需要同步。

异步回调示例:

return myAsyncMethod(param1, param2, (result, exc, att) -> {
    try {
        if (exc != null) {
            return handleError(exc); //cleanup resources and invoke parentHandler.complete(null, exc, null)
        } else {
            return handleResult(result);
        }
    } catch (Exception e) {
        return handleError(exc); //cleanup resources and invoke parentHandler.complete(null, exc, null)
    }
});
于 2014-06-23T05:27:20.033 回答