More Related Content
More from Akihiro Kitada (13)
Reactive Streams に基づく非同期処理プログラミング 〜 Reactor を使ってみた
- 3. Reactive Streams に基づく非同期処理考察(1/2)
処理対象データは、ストリームとして任意の量・タ
イミングで投入される – Reactor で言うところの
“hot-stream” の考え方。
処理対象データは、I/O レベルの “non-blocking” の
考え方に沿って、システムリソース節約のため、多
くの待機スレッドでデータ待ちをするのではなく、
必要に応じて、できるだけ少ないスレッドで処理す
る。
3
- 6. 実装
6
Publisher Subscriber
ここでは、non-blocking と back-pressure の考え
方に基づく非同期処理を、Reactive Streams の
Java 実装の一つである Ractor を使用して実現
します。
複数データを投入・処理するため
Flux を使用し、非同期処理を行うた
め TopicProcessor を使用します。
オプションで、back-pressure 動作
をカスタマイズするため、
BaseSubscriber を適用します。
- 8. 準備 – データ型の定義
8
package quitada;
public class KeyValuePair {
private String key;
private String value;
public KeyValuePair() { }
public KeyValuePair(String key, String value) {
this.key = key;
this.value = value;
}
public String getValue() { return value; }
public String getKey() { return key; }
public void setKey(String key) { this.key = key; }
public void setValue(String value) { this.value = value; }
}
なんでも良いのですが、ここでは
キー・バリュー・ペアなデータ型
を定義してみました。
- 9. TopicProcessor<KeyValuePair> hotSource = TopicProcessor.create();
Flux<KeyValuePair> hotFlux = hotSource.publish().autoConnect();
hotFlux.subscribe(keyValuePair -> {
// KeyValuePair 型のデータに対する何かの処理を記述
:
});
for (int i = 1; i <= 1000 ; i++) {
String value = Integer.toString(i);
hotSource.onNext(new KeyValuePair("k" + value, "v" + value));
}
僕のリアクティブな非同期処理実装
9
データ処理を非同期に行うため、
hot-stream なデータソースを
TopicProcessor 使って作成します。
Flux を使って Publisher と
Subscriber を準備します。
受信したデータの処理ロジックを
登録します。
データストリームとして、データ
投入します - Flux#onNext([処理対
象データ])。これにより、データ
投入処理とは非同期に逐次登録し
た処理ロジックが実行されます。
- 10. [オプション] back-pressure 動作のカスタマイズ
10
TopicProcessor<KeyValuePair> hotSource = TopicProcessor.create();
Flux<KeyValuePair> hotFlux = hotSource.publish().autoConnect();
BaseSubscriber<KeyValuePair> subscriber = new BaseSubscriber<KeyValuePair>() {
protected void hookOnSubscribe(Subscription subscription) {
request(1);
}
protected void hookOnError(Throwable throwable) {
throwable.printStackTrace();
}
protected void hookOnComplete() { }
protected void hookOnNext(KeyValuePair keyValuePair) {
// KeyValuePair 型データに対する何らかの処理を記述
:
request(1);
}
};
hotFlux.subscribe(subscriber);
for (int i = 1; i <= 1000 ; i++) {
String value = Integer.toString(i);
hotSource.onNext(new KeyValuePair("k" + value, "v" + value));
}
BaseSubscriber を使って、back-
pressure 動作をカスタマイズでき
ます(デフォルトでは、登録した
ロジックが実行し終わったら適宜
要求するような動作)。
BaseSubscriber#request([要求
データ数]) を任意のタイミングで
実行することで、フローコント
ロールを行います。この例では、
ロジック登録時と、ロジック実行
完了時に 1 つデータを要求すると
いう単純なロジックで、デフォル
トの挙動と同じです。データ要求
しないと、当然のことながら処理
が止まります。