我有一个从本地数据库中检索到的对象数组,需要按照API调用的顺序上传到服务器。 对于每个本地DB对象,我必须随后调用两个异步API调用(methodA(),methodB())。在完成整个循环之后,我需要调用另一个API调用,如下所示。
for(Object object: localDBObjects){
methodA() -> methodB()
}
methodC()
我的问题是如何在完成循环之前阻止methodC()调用。
答案 0 :(得分:3)
这个怎么样:
public class Main {
public static CountDownLatch finishLatch = new CountDownLatch(1);
public static Integer methodA(Integer obj) {
try {
Thread.sleep((int) (Math.random() * 1000)); //Simulate asynchronous call
} catch (InterruptedException e) {
}
System.out.println("methodA for " + obj + " executed by " + Thread.currentThread().getName());
return obj;
}
public static Integer methodB(Integer obj) {
try {
Thread.sleep((int) (Math.random() * 1000)); //Simulate asynchronous call
} catch (InterruptedException e) {
}
System.out.println("methodB for " + obj + " executed by " + Thread.currentThread().getName());
return obj;
}
public static void methodC() {
System.out.println("methodC executed by " + Thread.currentThread().getName());
finishLatch.countDown(); //Allow main to finish
}
public static void main(String[] args) throws IOException, InterruptedException {
List<Integer> objectsFromDb = Arrays.asList(1, 2, 3, 4, 5); //List of objects from the DB
Observable.from(objectsFromDb)
.flatMap(obj -> Observable.fromCallable(() -> methodA(obj)).subscribeOn(Schedulers.io())) //Asynchronously call method A
.flatMap(obj -> Observable.fromCallable(() -> methodB(obj)).subscribeOn(Schedulers.io())) //Asynchronously call method B
.doOnCompleted(() -> methodC()) //When finished, call methodC
.subscribe();
finishLatch.await(); //Wait for everything to finish
}
}
示例输出:
methodA for 5 executed by RxCachedThreadScheduler-5
methodA for 2 executed by RxCachedThreadScheduler-2
methodA for 1 executed by RxCachedThreadScheduler-1
methodB for 1 executed by RxCachedThreadScheduler-2
methodB for 2 executed by RxCachedThreadScheduler-5
methodB for 5 executed by RxCachedThreadScheduler-6
methodA for 3 executed by RxCachedThreadScheduler-3
methodA for 4 executed by RxCachedThreadScheduler-4
methodB for 3 executed by RxCachedThreadScheduler-1
methodB for 4 executed by RxCachedThreadScheduler-2
methodC executed by RxCachedThreadScheduler-2
答案 1 :(得分:1)
由于我没有获得关于你的项目的大量信息和方法的具体实现,即他们的论点和返回类型,我有2个假设。
注意:我希望您不要介意我是否会使用lambda表达式。
1)。方法返回Observable<Object>
,如Retrofit
在这种情况下,它们看起来像这样:
public Observable<Object> methodA(Object o){
return null;
}
public Observable<Object> methodB(Object o){
return null;
}
public Observable<Object> methodC(Object[] objects){
return null;
}
对于这种情况,您可以使用以下内容:
Object[] localDBObjects = new Object[10];
Observable.just(localDBObjects)
.flatMap(objects -> Observable.from(objects)
.flatMap(object -> methodA(object))
.flatMap(resultFromMethodA -> methodB(resultFromMethodA))
.toList())
.flatMap(listOfResultsFromMethodB -> methodC(listOfResultsFromMethodB.toArray(new Object[listOfResultsFromMethodB.size()])))
.subscribe(resultFromMethodC -> {
//do something
}, t -> t.printStackTrace());
2)。在其他情况下,方法返回Object
,如下所示:
public Object methodA(Object o){
return null;
}
public Object methodB(Object o){
return null;
}
public Object methodC(Object[] objects){
return null;
}
在这种情况下,您需要在某些地方将运算符flatMap( )
更改为map( )
:
Object[] localDBObjects = new Object[10];
Observable.just(localDBObjects)
.flatMap(objects -> Observable.from(objects)
.map(object -> methodA(object))
.map(resultFromMethodA -> methodB(resultFromMethodA))
.toList())
.map(listOfResultsFromMethodB -> methodC(listOfResultsFromMethodB.toArray(new Object[listOfResultsFromMethodB.size()])))
.subscribe(resultFromMethodC -> {
//do something
}, t -> t.printStackTrace());