我有一个整数列表,对于每个整数,我想从数据库中获取一个字符串值,并将其放入一个Map中,其中Integer是父列表中的int值,String是从中取出的字符串值数据库。我也想要,让字符串并行运行。
这就是我用RxJava实现的方法。我的代码有效,我得到了预期的结果,但我不认为提取名称是并行的。
public Observable<Map<Integer, String>> getVitalsForConnectedDevices(int accountId) {
List<Integer> ids = Lists.newArrayList(2, 3, 5);
return Observable<Map<Integer, String>> obs = Observable.from(ids)
.flatMap((Func1<Integer, Observable<Map.Entry<Integer, String>>>) integer
-> Observable.just(Maps.immutableEntry(integer, deviceDAO.getVitalName(integer)))
.subscribeOn(Schedulers.io()), 20)
.toMap(entry -> entry.getKey(), entry -> entry.getValue());
}
这是getVitalName()方法
public String getVitalName(int vitalId) {
log.debug("id: " + vitalId);
String query = "SELECT name FROM vitals WHERE vital_id=?";
String name = v1JdbcTemplate.queryForObject(query, String.class, vitalId);
log.debug("name: " + name);
return name;
}
按以下顺序打印上述函数的调试语句:
09-10-2017 02:05:37 DEBUG DeviceDAO:118 - id: 2
09-10-2017 02:05:37 DEBUG DeviceDAO:121 - name: Steps
09-10-2017 02:05:37 DEBUG DeviceDAO:118 - id: 3
09-10-2017 02:05:37 DEBUG DeviceDAO:121 - name: Floors
09-10-2017 02:05:37 DEBUG DeviceDAO:118 - id: 5
09-10-2017 02:05:37 DEBUG DeviceDAO:121 - name: Distance
如果它是并行运行的,那么它不应该先打印所有id的名字,以后再打印吗?我在这做错了什么?如何让它们并行运行?
答案 0 :(得分:1)
不应该首先打印所有ID并稍后命名
答案是否定的,因为您要从数据库中请求每个id一个String。结果完成后,将Id和String打包到一个Entry中并将其向下推送到管道中。请注意,如果所有flatMaps完成或发出错误,toMap将仅成功完成。所以可能会等待一段时间才能获得最终结果。
作为示例:您迭代超过5个ID。所有请求都是并行触发的。由于负载,服务器处于困境,因此一些请求将花费一些时间。让我们说一个请求已经完成但只有一个。仅在最后一个请求完成时,结果Map&lt;&gt;将推送给订户。如果这是你想要的,那么我建议你返回一个&lt;&gt;不是观察者。
以下是输出测试:
@Test
void name() throws Exception {
Observable<Tuple2<Integer, String>> tuple2Observable = Observable.just(1, 2, 3, 4, 5, 6)
.flatMap(integer ->
Observable.fromCallable(() -> getVitalName(integer))
.subscribeOn(Schedulers.io())
.doOnNext(s -> System.out.println("Value:: " + Thread.currentThread().getName() + "-" + Instant.now()))
.map(s -> Tuple.of(integer, s))
).doOnComplete(() -> System.out.println("Finished:: " + Thread.currentThread().getName() + "-" + Instant.now()));
tuple2Observable.test()
.await();
}
public String getVitalName(int vitalId) throws Exception {
System.out.println("getVitalName method called with vitalId = " + vitalId + "-" + Thread.currentThread().getName() + "-" + Instant.now());
Thread.sleep(500);
String name = "le fake value";
return name;
}
你看,确实在不同的线程上同时创建了calles,并且当所有请求都完成时,observable完成了。
getVitalName method called with vitalId = 4-RxCachedThreadScheduler-4-2017-10-08T21:20:43.785Z
getVitalName method called with vitalId = 6-RxCachedThreadScheduler-6-2017-10-08T21:20:43.786Z
getVitalName method called with vitalId = 5-RxCachedThreadScheduler-5-2017-10-08T21:20:43.785Z
getVitalName method called with vitalId = 1-RxCachedThreadScheduler-1-2017-10-08T21:20:43.785Z
getVitalName method called with vitalId = 2-RxCachedThreadScheduler-2-2017-10-08T21:20:43.784Z
getVitalName method called with vitalId = 3-RxCachedThreadScheduler-3-2017-10-08T21:20:43.787Z
Value:: RxCachedThreadScheduler-4-2017-10-08T21:20:44.303Z
Value:: RxCachedThreadScheduler-6-2017-10-08T21:20:44.303Z
Value:: RxCachedThreadScheduler-1-2017-10-08T21:20:44.304Z
Value:: RxCachedThreadScheduler-2-2017-10-08T21:20:44.304Z
Value:: RxCachedThreadScheduler-3-2017-10-08T21:20:44.304Z
Value:: RxCachedThreadScheduler-5-2017-10-08T21:20:44.304Z
Finished:: RxCachedThreadScheduler-4-2017-10-08T21:20:44.317Z