[英]Processing changing source data in Java Akka streams
啟動了 2 個線程。 dataListUpdateThread
將數字 2 添加到List
。 processFlowThread
對同一List
中的值求和,並將求和后的列表打印到控制台。 這是代碼:
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import static java.lang.Thread.sleep;
public class SourceExample {
private final static ActorSystem system = ActorSystem.create("SourceExample");
private static void delayOneSecond() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void printValue(CompletableFuture<Integer> integerCompletableFuture) {
try {
System.out.println("Sum is " + integerCompletableFuture.get().intValue());
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
final List dataList = new ArrayList<Integer>();
final Thread dataListUpdateThread = new Thread(() -> {
while (true) {
dataList.add(2);
System.out.println(dataList);
delayOneSecond();
}
});
dataListUpdateThread.start();
final Thread processFlowThread = new Thread(() -> {
while (true) {
final Source<Integer, NotUsed> source = Source.from(dataList);
final Sink<Integer, CompletionStage<Integer>> sink =
Sink.fold(0, (agg, next) -> agg + next);
final CompletionStage<Integer> sum = source.runWith(sink, system);
printValue(sum.toCompletableFuture());
delayOneSecond();
}
});
processFlowThread.start();
}
}
我試圖創建一個最簡單的例子來構建問題。 dataListUpdateThread
可以從 REST 服務或 Kafka 主題填充列表,而不僅僅是將值 2 添加到列表中。 而不是使用 Java 線程應該如何實現這種場景? 也就是說,如何將dataList
共享給Akka Stream進行處理?
改變傳遞給Source.from
的集合只是巧合:如果集合用盡, Source.from
將完成 stream。 這是因為它適用於有限的、嚴格評估的數據(用例基本上是:a)文檔的簡單示例和 b)在后台執行集合操作時想要限制資源消耗的情況(想想列表您想要發送 HTTP 請求到的 URL))。
注意:自從 Java 7 天以來,我沒有在很大程度上寫過 Java,所以我沒有提供 Java 代碼,只是一個概述。
正如前面的回答中提到的, Source.queue
可能是最好的選擇(除了使用 Akka HTTP 或 Alpakka 連接器之類的東西)。 在這種情況下,流的具體化值是一個未來,直到 stream 完成后才會完成, Source.queue
將永遠不會完成 stream(因為它無法知道它的引用是唯一的參考),引入一個KillSwitch
並通過viaMat
和toMat
傳播它將使您能夠在 stream 之外決定完成 stream。
Source.actorRef
Source.queue
它可以讓您發送一條可區分的消息( akka.Done.done()
很常見)。 該源具體ActorRef
,您可以向其tell
消息,並且這些消息(至少與流類型匹配的消息)將可供 stream 使用。
使用Source.queue
和Source.actorRef
, prematerialize
它們通常很有用:在像您的示例這樣您還需要接收器的物化值的情況下,替代方法是大量使用Mat
運算符來自定義物化值(在 Scala 中,可以使用元組至少簡化多個物化值的組合,但是在 Java 中,一旦超出了一對(就像使用queue
一樣),我很確定你必須定義一個 ZA2DZC21 到 222F8EBC2保存三個(隊列,killswitch,完成值的未來)物化值)。
還值得注意的是,由於 Akka 流在后台運行在 Actor 上(因此根據需要安排到ActorSystem
的線程上),幾乎沒有理由創建一個線程來運行 stream。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.