实现思路
Dispatchers
:用于指定协程运行的线程上下文,例如 Dispatchers.IO
适用于I/O密集型任务,Dispatchers.Default
适用于CPU密集型任务。
CoroutineScope
:定义协程的作用域,控制协程的生命周期。
Semaphore
:用于限制并发数量,它类似于一个计数器,每次获取信号量时计数器减一,释放信号量时计数器加一。
代码示例
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Semaphore
// 定义最大并发数
private const val MAX_CONCURRENT_REQUESTS = 3
fun main() = runBlocking {
// 创建一个信号量,初始值为最大并发数
val semaphore = Semaphore(MAX_CONCURRENT_REQUESTS)
// 创建一个协程作用域
val coroutineScope = CoroutineScope(Job() + Dispatchers.Default)
// 模拟多个网络请求
val requests = (1..10).map { requestNumber ->
coroutineScope.async {
// 获取信号量,若信号量不足则等待
semaphore.acquire()
try {
// 模拟网络请求
delay((1000 * (1..3).random()).toLong())
println("Request $requestNumber completed")
} finally {
// 释放信号量
semaphore.release()
}
}
}
// 等待所有请求完成
requests.forEach { it.await() }
// 取消协程作用域
coroutineScope.cancel()
}
代码功能解释
MAX_CONCURRENT_REQUESTS
:定义了允许同时执行的最大网络请求数量。
Semaphore(MAX_CONCURRENT_REQUESTS)
:创建一个信号量实例,初始值为 MAX_CONCURRENT_REQUESTS
,表示最多允许 MAX_CONCURRENT_REQUESTS
个协程同时执行。
CoroutineScope(Job() + Dispatchers.Default)
:创建一个协程作用域,使用 Dispatchers.Default
作为线程上下文,Job
用于管理协程的生命周期。
semaphore.acquire()
:获取信号量,如果当前信号量的值为0(即所有允许的并发任务都在执行中),则当前协程会被挂起,直到有信号量可用。
semaphore.release()
:释放信号量,使信号量的值加一,允许其他等待的协程获取信号量并继续执行。
delay((1000 * (1..3).random()).toLong())
:模拟网络请求的延迟,每次延迟时间在1秒到3秒之间随机。
requests.forEach { it.await() }
:等待所有异步任务完成。
coroutineScope.cancel()
:取消协程作用域,确保所有协程在程序结束时正确清理。