我正在尝试并行运行 2 个函数,之后我想使用前 2 个函数的结果启动第三个函数。
我搜索了 Google 和 StackOverflow,并尝试了下面的代码。
但是 func2() 是在 func1() 完成之后才开始的,而不是并行的。
日志如下。
开始 func1 -> 结束 func1 -> 开始 func2 -> 结束 func2 -> 10 + 20 = 30
如何并行运行 2 个函数?
val TAG = "TagMainActivity"
val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
lifecycleScope.launch(dispatcher) {
val job1 = async { func1() }
val job2 = async { func2() }
func3(job1.await(), job2.await())
}
}
suspend fun func1(): Int {
Log.d(TAG, "Start func1")
Thread.sleep(3000)
Log.d(TAG, "End func1")
return 10
}
suspend fun func2(): Int {
Log.d(TAG, "Start func2")
Thread.sleep(3000)
Log.d(TAG, "End func2")
return 20
}
suspend fun func3(bmp1: Int, bmp2: Int) {
Log.d(TAG, "$bmp1 + $bmp2 = ${bmp1 + bmp2}")
}
您使用 async 并行运行 func1() 和 func2(),在它们都完成后,您调用 func3() 对结果求和。然而,在挂起函数中使用 Thread.sleep() 有一个小问题 — 这是一个阻塞操作,应该替换为像 delay() 这样的非阻塞挂起函数。
Thread.sleep() 会阻塞线程并可能导致性能问题,尤其是在协程中。由于您已经在使用协程,因此您应该使用delay()来挂起协程而不阻塞线程。
val TAG = "TagMainActivity"
val dispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Launch the coroutine in a custom dispatcher
lifecycleScope.launch(dispatcher) {
val job1 = async { func1() }
val job2 = async { func2() }
// Wait for both jobs to finish and call func3
func3(job1.await(), job2.await())
}
}
// Non-blocking version of func1 using delay instead of Thread.sleep
suspend fun func1(): Int {
Log.d(TAG, "Start func1")
delay(3000) // Non-blocking delay
Log.d(TAG, "End func1")
return 10
}
// Non-blocking version of func2 using delay instead of Thread.sleep
suspend fun func2(): Int {
Log.d(TAG, "Start func2")
delay(3000) // Non-blocking delay
Log.d(TAG, "End func2")
return 20
}
// Function to log the results after both func1 and func2 are done
suspend fun func3(bmp1: Int, bmp2: Int) {
Log.d(TAG, "$bmp1 + $bmp2 = ${bmp1 + bmp2}")
}
override fun onDestroy() {
super.onDestroy()
dispatcher.close() // Clean up the dispatcher to avoid memory leaks
}
用delay()替换Thread.sleep():由于Thread.sleep()是阻塞调用,它可以冻结整个线程。 delay() 挂起协程而不阻塞线程,这对于协程来说更合适。
您应该在onDestroy()中调用dispatcher.close()来正确清理SingleThreadExecutor以避免内存泄漏。如果您使用的是标准调度程序(例如 Dispatchers.IO 或 Dispatchers.Default),则可以跳过此步骤。