【发布时间】:2021-06-13 17:55:05
【问题描述】:
使用下面的代码,我尝试使用演员作为源并发送 Double 类型的消息以通过滑动窗口进行处理。
滑动窗口被定义为sliding(2, 2)来计算每个发送的twp值序列。
发送消息:
actorRef.tell(10, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(30, ActorRef.noSender());
actorRef.tell(40, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
应按如下方式计算平均值:
10 + 20 / 2 = 15
30 + 40 / 2 = 35
但在下面的代码中似乎没有调用计算。
这里我输出值:
movingAverage.runForeach(n -> {
if( n > 0){
System.out.println(n);
}
}, system);
源代码:
import akka.Done;
import akka.actor.ActorRef;
import akka.stream.CompletionStrategy;
import akka.stream.OverflowStrategy;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import java.util.Optional;
public class FilterThreshold {
public static void main(String[] args) {
final akka.actor.ActorSystem system = akka.actor.ActorSystem.create("Source");
final int bufferSize = 1;
final Source<Double, ActorRef> source =
Source.actorRef(
elem -> {
// complete stream immediately if we send it Done
if (elem == Done.done()) {
return Optional.of(CompletionStrategy.immediately());
} else {
return Optional.empty();
}
},
// never fail the stream because of a message
elem -> Optional.empty(),
bufferSize,
OverflowStrategy.dropHead());
ActorRef actorRef = source.to(Sink.foreach(System.out::println)).run(system);
actorRef.tell(10, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(30, ActorRef.noSender());
actorRef.tell(40, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
Source<Double, ActorRef> movingAverage = source
.sliding(2, 2)
.map(window -> (window.stream().mapToDouble(i -> i).sum()) / window.size());
movingAverage.runForeach(n -> {
if( n > 0){
System.out.println(n);
}
}, system);
}
}
我已经编辑了来自https://doc.akka.io/docs/akka/current/stream/operators/Source-or-Flow/sliding.html的代码
如何应用定义为movingAverage 的滑动窗口函数来计算通过Akka actor actorRef 发送的值?
更新:
permaterialize 方法将参与者系统作为参数。
从以下位置更新代码:
final Pair<ActorRef, Source<Double, ActorRef>> prematPair = source.preMaterialize();
到:
final Pair<ActorRef, Source<Double, ActorRef>> prematPair = source.preMaterialize(system);
导致编译时错误:
Required type:
Pair
<ActorRef,
Source<Double, ActorRef>>
Provided:
Pair
<ActorRef,
Source<Double, NotUsed>>
我应该使用其他方法吗?
已发布更新代码:
import akka.Done;
import akka.NotUsed;
import akka.actor.ActorRef;
import akka.japi.Pair;
import akka.stream.CompletionStrategy;
import akka.stream.OverflowStrategy;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import java.util.Optional;
public class FilterThreshold {
public static void main(String[] args) {
final akka.actor.ActorSystem system = akka.actor.ActorSystem.create("Source");
final int bufferSize = 1;
final Source<Double, ActorRef> source =
Source.actorRef(
elem -> {
System.out.println("elem is "+elem);
// complete stream immediately if we send it Done
if (elem == Done.done()) {
return Optional.of(CompletionStrategy.immediately());
} else {
return Optional.empty();
}
},
// never fail the stream because of a message
elem -> Optional.empty(),
bufferSize,
OverflowStrategy.dropHead());
// source is as before
final Pair<ActorRef, Source<Double, ActorRef>> prematPair = source.preMaterialize(system);
Flow<Double, Double, NotUsed> movingAverageFlow =
Flow.of(Double.class)
.sliding(2, 2)
.map(window -> (window.stream().mapToDouble(i -> i).sum()) / window.size());
final Source<Double, ActorRef> prematSource = prematPair.second();
prematSource.via(movingAverageFlow).runForeach(n -> {
System.out.println("n is "+n);
if (n > 0) {
System.out.println(n);
}
}, system);
final ActorRef actorRef = prematPair.first();
actorRef.tell(10, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
}
}
更新2:
使用代码:
import akka.Done;
import akka.NotUsed;
import akka.actor.ActorRef;
import akka.japi.Pair;
import akka.stream.CompletionStrategy;
import akka.stream.OverflowStrategy;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import java.util.Optional;
public class FilterThreshold {
public static void main(String[] args) {
final akka.actor.ActorSystem system = akka.actor.ActorSystem.create("Source");
final int bufferSize = 1;
final Source<Double, ActorRef> source =
Source.actorRef(
elem -> {
System.out.println("elem is "+elem);
// complete stream immediately if we send it Done
if (elem == Done.done()) {
return Optional.of(CompletionStrategy.immediately());
} else {
return Optional.empty();
}
},
// never fail the stream because of a message
elem -> Optional.empty(),
bufferSize,
OverflowStrategy.dropHead());
// source is as before
final Pair<ActorRef, Source<Double, NotUsed>> prematPair = source.preMaterialize(system);
final ActorRef actorRef = prematPair.first();
final Source<Double, NotUsed> prematSource = prematPair.second();
Flow<Double, Double, NotUsed> movingAverageFlow =
Flow.of(Double.class)
.sliding(2, 2)
.map(window -> (window.stream().mapToDouble(i -> i).sum()) / window.size());
prematSource.via(movingAverageFlow).runForeach(n -> {
System.out.println("n is "+n);
if (n > 0) {
System.out.println(n);
}
}, system);
actorRef.tell(10, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
actorRef.tell(20, ActorRef.noSender());
prematSource.run(system);
}
}
打印:
elem is 10
elem is 20
elem is 20
elem is 20
elem is 20
看来消息发送正确,但移动平均线并未实现。
使用prematSource.run(system); 不是实现价值的正确方法吗?
【问题讨论】:
标签: java akka akka-stream