对于线程来说,同步异步是一个行为、阻塞非阻塞是一种状态。协程在某些方面与线程类似,如挂起、切换。但协程是工作在线程之上的。协程的切换可以由程序控制,不需要操作系统调度。
launch :创建协程。
runBlocking:最高级协程,也是主协程,launch 创建的协程能够在 runBlocking 中运行,反过来不可以。
fun main() = runBlocking {
GlobalScope.launch {
delay(1000L)
println("world")
}
println("hello")
Thread.sleep(2000L)
}
delay :只能在协程内部使用,它用于挂起协程,不会阻塞线程。
sleep:用来阻塞线程。
job.join() :非阻塞式等待,直到线程结束,不会将当前线程挂起。
async :创建子协程,与其他协程并行工作,返回的式 Deferred 对象,Deferred 值是一个非阻塞可取消的 future,它是一个带有结果的 job。
awai :可以去除返回值。
fun main() = runBlocking {
val async1 = async { }
val async2 = async { }
async1.await()
async2.await()
}
重点来了,launch 的源码
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
CoroutineContext :接收一个可选的 CoroutineContext 参数,是一些元素的集合,主要包括 Job 和 CoroutineDispatcher 元素。可以代表一个协程的场景。默认值EmptyCoroutineContext,表示运行在父协程的上下文中。
CoroutineDispatcher 可以指定协程运行在某一特定线程上、运作在线程池中或者不指定所运行的线程,协程调度器可以分为 Confined Dispatcher 和 Unconfined Dispatcher。
Confined Dispatcher 指定了协程所运行的线程或线程池,挂起函数恢复后协程也是运行在指定的线程或线程池上,如下几类:
Dispatchers.Default :将会获取默认调度器,使用共享的后台线程池
Dispatchers.IO :运行在IO线程中
Dispatchers.Main :运行在主线程中
Unconfined Dispatcher 如:
Dispatchers.Unconfined :协程调度器会在程序运行到第一个挂起点时,在调用者线程中启动。挂起后,它将在挂起函数执行的线程中恢复,恢复的线程完全取决于该挂起函数在哪个线程执行。非受限调度器适合协程不消耗 CPU 时间也不更新任何限于特定线程的共享数据(如 UI)的情境。
当然也可以使用 newFixedThreadPoolContext 和 newSingleThreadContext 等创建 context;
CoroutineStart
一般情况下默认 DEFAULT 即可,会根据上下文去启动协程。另外还有有 LAZY 模式,可以延迟启动,注意当协程在执行前被取消后,它不会再执行了。
withContext
此函数不会创建新的协程,在指定协程上运行挂起代码块,并挂起该协程直至代码块运行完成。它同样可以指定 CoroutineContext 。
此篇简单介绍下 Kotlin 的协程,深入的源码这里就不详细解释了。
最后说下 kotlin 中使用 同步方法
@Volatile
private var count: Int = 1;
@Synchronized
fun buy() {
}
fun buy2() {
synchronized(this) {
}
}
也可以使用 Lock 加锁,Kotlin 提供的方法:
public inline fun Lock.withLock(action: () -> T): T {
lock()
try {
return action()
} finally {
unlock()
}
}