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 を 3 つの引数を持つ関数型インターフェイスに変換する単純なラッパーです。

ともかく。オフセットは「アタッチメント」パラメーターに入れることができ、ラムダは事前に宣言してフィールドとして再利用できます。ただし、結果として得られるコードは常に醜い醜い醜いものです。

このような単純なタスクでも、許容できるソリューションを作成できませんでした。読み取りが書き込みとインターリーブされ、複雑なロジックでラップされる複雑なプロトコルの場合はどうなるでしょうか。

非同期APIを処理する適切な方法を知っている人はいますか? ここで Scala が世界を救うことができると思われる場合は、気軽に使用してください。

4

2 に答える 2

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 に答える