簡體   English   中英

處理 Java Akka 流中更改的源數據

[英]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並通過viaMattoMat傳播它將使您能夠在 stream 之外決定完成 stream。

Source.actorRef Source.queue它可以讓您發送一條可區分的消息( akka.Done.done()很常見)。 該源具體ActorRef ,您可以向其tell消息,並且這些消息(至少與流類型匹配的消息)將可供 stream 使用。

使用Source.queueSource.actorRefprematerialize它們通常很有用:在像您的示例這樣您還需要接收器的物化值的情況下,替代方法是大量使用Mat運算符來自定義物化值(在 Scala 中,可以使用元組至少簡化多個物化值的組合,但是在 Java 中,一旦超出了一對(就像使用queue一樣),我很確定你必須定義一個 ZA2DZC21 到 222F8EBC2保存三個(隊列,killswitch,完成值的未來)物化值)。

還值得注意的是,由於 Akka 流在后台運行在 Actor 上(因此根據需要安排到ActorSystem的線程上),幾乎沒有理由創建一個線程來運行 stream。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM