又上了一周班了(
1.
问题:需要发一堆HTTP请求,一个请求平均10s,所以需要并行,一个很正常的需求。于是学习了一下kotlin协程。
协程:建立在线程之上。一个线程可以运行成百上千的协程。可以使用调度器决定协程在哪个线程上运行。当一个协程挂起的时候,线程可以执行其他协程。
runBlocking:创建一个作用域,等里面所有协程都结束后出来。
async,launch:创建一个协程,async可以通过调用await获取结果,launch适用于不需要运行结果的场景。
Dispatcher:调度器。有的调度器,如Dispatcher.IO会创建一个线程池,然后在上面调度协程。
接下来写了一段代码:
runBlocking { files.map { file -> async {...//发HTTP请求} }.awaitAll() }
运行了一下,发现还是串行的。因为发HTTP请求的操作是阻塞的,也就是说,等待结果期间协程并没有被挂起,也就不会执行其他协程,而是干等着。
于是有两个选择:一是使用异步HTTP请求,二是使用调度器。一的话会涉及到和Java的交互,比较麻烦,因此选择async(Dispatcher.IO)就可以了。
关于协程的其他部分这篇讲得非常好了。
然后超过目标服务器并行限制了
2.
修改了一些代码于是要改对应的test。已知添加了一个判断条件SystemProperties.get(),需要在测试里给定这个静态方法一个测试用的的值。
Mockito不能mock静态方法,于是有了ExtendedMockito,可以通过加载类时改字节码的方式mock静态方法。但这听起来不是一个test该干的事。一个解决方案是将该静态方法以参数的方式传递到类中,这样test的时候就可以把它替换掉,像这样:
class Person(val name: String, var age: Int val height: () -> Int = { SystemProperties.get(...) } )
然后test的时候这样:
var height: Int = 0 @Before fun setUp() { person = Person("Alice",10) { height } }
用的时候修改height的值即可。听上去有哪不对。kotlin的lambda函数用的是height的引用,所以是对的。
但是出现了新的问题。由于这段代码需要和Java交互,Java不直接支持默认参数。因此需要@JvmOverLoads让编译器生成两个构造函数,像这样:
class Person