Kotlin遇到一个任务由多个接口才能完成时,如何优雅的执行

前言

不想华丽胡哨的写了,直接说问题和处理办法。

今天遇到一个需求,举个相同的例子说明,就是有两个接口A、B,A是获取某一段范围内用户的姓名列表,接口B中是根据用户的姓名查找这个用户的爱好,那么要通过ListView展示A接口+B接口中的数据,如何优雅的写?

image.png

肯定要先调用A接口吧,然后循环调用B接口?,B接口的请求回调中关联上指定的姓名,然后在设置适配器。

不同的人肯定有不同的写法,所以直接上我认为比较优雅的方法吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
kotlin复制代码import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionService
import java.util.concurrent.ExecutorCompletionService
import java.util.concurrent.ExecutorService
import java.util.function.Supplier
import java.util.stream.Collector
import java.util.stream.Collectors
import java.util.stream.Stream

fun syncPost(name: String): String {
return "爱好${(0..10).random()}"
}

var map = mutableMapOf<String, String>()
fun getHobby(name: String, map: MutableMap<String, String>): CompletableFuture<Unit> {
return CompletableFuture.supplyAsync {
Thread.sleep((0..1000).random().toLong())
map[name] = syncPost(name)
}
}

fun main() {
var listName = Stream.generate { "李${(0..10).random()}" }.limit(10).collect(Collectors.toSet())
var exec = mutableListOf<CompletableFuture<Unit>>()
println(map)
listName.forEach {
exec.add(getHobby(it, map))
}
var allOf = CompletableFuture.allOf(*exec.toTypedArray()).thenAccept {
println("执行完成")
println(map)
}
allOf.get()

}

原理还是利用了CompletableFuture,首先 CompletableFuture是Future的扩展,意味着更强,并且解决了Future不能完成的事情,如本例就用到了Future所没有的功能,也就是将多个异步任务一起执行。

还有个更方便的方法,CompletableFuture提供了一个回调功能,这个回调是在所有任务都完成后被调用,也就是thenAccept方法,如果通过循环调用请求,如何判断所有的请求都执行完毕?是不是需要一个变量累加或是别的方法,但是感觉还有没有thenAccept方便吧。

同样我们可以指定超时时间,时间到达后如果还没有全部完成,则抛出TimeoutException。

1
2
3
4
5
java复制代码try {
allOf.get(500, TimeUnit.MILLISECONDS)
} catch (ep: TimeoutException) {
ep.printStackTrace()
}

另外如果在任务中异常没有捕获,那么并不会影响其他的任务,但是不会执行thenAccept,需要注意的是,如果在任务中抛出异常,并不会立马输出,而是在全部任务结束后才被真正抛出。

1
2
3
4
5
6
7
8
9
10
java复制代码fun getHobby(name: String, map: MutableMap<String, String>): CompletableFuture<Unit> {
return CompletableFuture.supplyAsync {
Thread.sleep((0..1000).random().toLong())
map[name] = syncPost(name)
if (name == "李2")
throw NullPointerException("null")
println("${Thread.currentThread().name}执行完毕")

}
}

如果某个任务失败,还需要把他加入到一个重试队列中。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%