我有一个热的可观察Observable<Resource> resources
代表可消耗资源,我想为这些资源排队消费者Action1<Resource>
。资源最多可由1个消费者使用。一旦从resources
推送新值,就不应该使用它。如果我的消费者也被热的观察所包裹,那么我所追求的大理石图将是
--A--B--C--D--E--
----1----2--34---
----A----C--D-E--
----1----2--3-4--
我使用PublishSubject
和zip
管理了一个简单的实现,但这仅适用于在发布新资源之前消耗每个资源(即代替所需的序列[A1, C2,D3,E4]这种实现实际上会产生[A1,B2,C3,D4])。
这是我第一次尝试使用rx而且我已经同时使用了delay
和join
,但似乎无法得到我所知道的后。我也读过,理想情况下应该避免使用Subjects
,但我不知道如何实现这一点。
public class ResourceQueue<Resource> {
private final PublishSubject<Action1<Resource>> consumers = PublishSubject.create();
public ResourceQueue(Observable<Resource> resources) {
resources.zipWith(this.consumers, new Func2<Resource, Action1<Resource>, Object>() {
@Override
public Object call(Resource resource, Action1<Resource> consumer) {
consumer.execute(resource);
return null;
}
}).publish().connect();
}
public void queue(final Action1<Resource> consumer) {
consumers.onNext(consumer);
}
}
有没有办法实现我之后的目标?是否有更多的&rx-y&#39;解决方案的方法?
答案 0 :(得分:0)
编辑:使用withLatesFrom更改了combineLatest建议。
我能想到的唯一解决方案是使用combineLatest获取所有可能的组合,手动排除您不需要的组合:
final ExecutorService executorService = Executors.newCachedThreadPool();
final Observable<String> resources = Observable.create(s -> {
Runnable r = new Runnable() {
@Override
public void run() {
final List<Integer> sleepTimes = Arrays.asList(200, 200, 200, 200, 200);
for (int i = 0; i < sleepTimes.size(); i++) {
try {
Thread.sleep(sleepTimes.get(i));
} catch (Exception e) {
e.printStackTrace();
}
String valueOf = String.valueOf((char) (i + 97));
System.out.println("new resource " + valueOf);
s.onNext(valueOf);
}
s.onCompleted();
}
};
executorService.submit(r);
});
final Observable<Integer> consumers = Observable.create(s -> {
Runnable r = new Runnable() {
@Override
public void run() {
final List<Integer> sleepTimes = Arrays.asList(300, 400, 200, 0);
for (int i = 0; i < sleepTimes.size(); i++) {
try {
Thread.sleep(sleepTimes.get(i));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("new consumer " + (i + 1));
s.onNext(i + 1);
}
s.onCompleted();
};
};
executorService.submit(r);
});
final LatestValues latestValues = new LatestValues();
final Observable<String> combineLatest = Observable.combineLatest(consumers, resources, (c, r) -> {
if (latestValues.alreadyProcessedAnyOf(c, r)) {
return "";
}
System.out.println("consumer " + c + " will consume resource " + r);
latestValues.updateWithValues(c, r);
return c + "_" + r;
});
combineLatest.subscribe();
executorService.shutdown();
executorService.awaitTermination(10, TimeUnit.SECONDS);
持有最新消费者和资源的班级。
static class LatestValues {
Integer latestConsumer = Integer.MAX_VALUE;
String latestResource = "";
public boolean alreadyProcessedAnyOf(Integer c, String r) {
return latestConsumer.equals(c) || latestResource.equals(r);
}
public void updateWithValues(Integer c, String r) {
latestConsumer = c;
latestResource = r;
}
}