在上一篇:Kotlin 协程使用自定义线程池中我们简单的使用自定义线程池作为异步协程async的上下文并完成了主线程等待线程池执行完毕的小例子。
但是开发过程中难免会有很多需要这种多线程跑的情况,比如从库里批量更新一批数据,或者是给某接口推一批数据。这种时候显然需要多线程,每次都把这些抄一遍似乎有点……“ 曾经沧海难为水 ”固然没错,不过我们既然用Kotlin,那么“ 当惯了县长,再回去当麻匪,恐怕有点不习惯 ”;接下来我们开始用Kotlin的思路去解决这个问题。
首先我们确定每次使用多线程只需要控制线程数,其次是线程内调用的方法;借助Kotlin的扩展函数、协程、内联函数等特性我们可以实现如下的扩展函数:
/** * Returns a list containing the results of applying the given [funWorker] function * to each element in the original collection. * @author 鹞之神乐 https://www.kagura.me */ inline fun <T> Iterable<T>.mapMultithreading(nThreads: Int = 5, crossinline funWorker: (T) -> Any?): Iterable<Any?> { val results = arrayOfNulls<Any>(count()) val coroutineDispatcher = Executors.newFixedThreadPool(nThreads).asCoroutineDispatcher() runBlocking { coroutineDispatcher.use { launch { forEachIndexed { index, arg -> async(coroutineDispatcher) { funWorker(arg).let { results[index] = it } } } }.join() } } return results.asIterable() }
我们成功的实现了一个多线程版本的map
函数,使用也是很简单。因为我们扩展了Iterable
所以我们可以直接list.mapMultithreading{}
使用,当然默认是5个线程,如果需要指定线程数可以 list.mapMultithreading(6){}
即可。当然,执行结果也类似map
函数返回List。如下代码所示:
// 默认5个线程 val resultList = (1..10).mapMultithreading{ Thread.sleep(1000) Thread.currentThread().name } // 自定义线程数,并在执行完毕后变量输出结果 val resultList = (1..10).mapMultithreading(6) { Thread.sleep(1000) return@mapMultithreading Thread.currentThread().name } resultList .forEach { println(it) }
那么就介绍到这里啦!最近也打算做个Kotlin工具类库,会把这个收录进去,到时候大家直接添加Maven坐标即可。
未经允许不得转载:鹞之神乐 » Kotlin中更优雅的使用多线程