fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch {
println("World!")
}
println("Hello,")
job.join() // 等待子协程completes
}
将任务抽象为函数
在协程内执行的函数要有个suspend声明
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch { doWorld() }
println("Hello,")
job.join()
}
suspend fun doWorld() {
println("World!")
}
比较协程和线程
fun main(args: Array<String>) = runBlocking<Unit> {
val t0 = System.currentTimeMillis()
val jobs =List(100_000) { // launch a lot of coroutines and list their jobs
launch {
delay(1000L)
}
}
jobs.forEach { it.join() } // wait for all jobs to complete
val t1 = System.currentTimeMillis()
println(t1-t0) //1.3秒
}
//使用Thead://Exception in thread "main"//java.lang.OutOfMemoryError: unable to create new native thread
fun main(args: Array<String>){
runThread()
}
fun runThread(){
val t0 = System.currentTimeMillis()
val jobs =List(100_000){
val t =Thread{
Thread.sleep(1000)
print(".")
}
t.start()
t
}
jobs.forEach{it.join()}
val t1 = System.currentTimeMillis()
println(t1-t0)
}
//将线程数量减小10倍,结果都还是3.6秒,可见协程的效率//原因是线程是系统资源,申请分配和销毁代价等很高。
协程就像守护线程
fun main(args: Array<String>) = runBlocking<Unit> {
launch {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
delay(1300L) // just quit after delay
}
//I'm sleeping 0 ...//I'm sleeping 1 ...//I'm sleeping 2 ...
取消协程
协程在delay的时候可以被取消
fun main(args: Array<String>) = runBlocking<Unit> {
val job = launch {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
delay(1300L)
println("main: I'm tired of waiting!")
job.cancel() // 取消任务
job.join() //等待任务完成
println("main: Now I can quit.")
}
/*
I'm sleeping 0 ...
I'm sleeping 1 ...
I'm sleeping 2 ...
main: I'm tired of waiting!
main: Now I can quit.
*/
协作取消
在CPU运算时,取消操作是没有用的,和线程很像
fun main(args: Array<String>) = runBlocking<Unit> {
val startTime = System.currentTimeMillis()
val job = launch {
var nextPrintTime = startTime
var i = 0while (i < 5) { // computation loop, just wastes CPU// print a message twice a secondif (System.currentTimeMillis() >= nextPrintTime) {
println("I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
}
使用isActive标志位
fun main(args: Array<String>) = runBlocking<Unit> {
val startTime = System.currentTimeMillis()
val job = launch {
var nextPrintTime = startTime
var i = 0while (isActive) { // cancellable computation loop// print a message twice a secondif (System.currentTimeMillis() >= nextPrintTime) {
println("I'm sleeping ${i++} ...")
nextPrintTime += 500L
}
}
}
delay(1300L) // delay a bit
println("main: I'm tired of waiting!")
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")
}
async函数
async和launch的区别在于,前者是Callable,后者是Runable,你应该懂的
// The result type of asyncSomethingUsefulOne is Deferred<Int>fun asyncSomethingUsefulOne() = async {
doSomethingUsefulOne()
}
// The result type of asyncSomethingUsefulTwo is Deferred<Int>fun asyncSomethingUsefulTwo() = async {
doSomethingUsefulTwo()
}
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // pretend we are doing something useful herereturn13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // pretend we are doing something useful here, tooreturn29
}
// note, that we don't have `runBlocking` to the right of `main` in this examplefun main(args: Array<String>) {
val time = measureTimeMillis {
// we can initiate async actions outside of a coroutineval one = asyncSomethingUsefulOne()
val two = asyncSomethingUsefulTwo()
// but waiting for a result must involve either suspending or blocking.// here we use `runBlocking { ... }` to block the main thread while waiting for the result
runBlocking {
println("The answer is ${one.await() + two.await()}")
}
}
println("Completed in $time ms")
}
CoroutineContext
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = arrayListOf<Job>()
jobs += launch(Unconfined) { //not confined -- will work with main thread
println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
}
jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
}
jobs += launch(CommonPool) { // will get dispatched to ForkJoinPool.commonPool (or equivalent)
println(" 'CommonPool': I'm working in thread ${Thread.currentThread().name}")
}
jobs += launch(newSingleThreadContext("MyOwnThread")) { // will get its own new thread
println(" 'newSTC': I'm working in thread ${Thread.currentThread().name}")
}
jobs.forEach { it.join() }
}
/*
'Unconfined': I'm working in thread main
'CommonPool': I'm working in thread ForkJoinPool.commonPool-worker-1'newSTC': I'm working in thread MyOwnThread
'coroutineContext': I'm working in thread main
*/
fun main(args: Array<String>) = runBlocking<Unit> {
val jobs = arrayListOf<Job>()
jobs += launch(Unconfined) { // not confined -- will work with main thread
println(" 'Unconfined': I'm working in thread ${Thread.currentThread().name}")
delay(500)
println(" 'Unconfined': After delay in thread ${Thread.currentThread().name}")
}
jobs += launch(coroutineContext) { // context of the parent, runBlocking coroutine
println("'coroutineContext': I'm working in thread ${Thread.currentThread().name}")
delay(1000)
println("'coroutineContext': After delay in thread ${Thread.currentThread().name}")
}
jobs.forEach { it.join() }
}
/*
'Unconfined': I'm working in thread main
'coroutineContext': I'm working in thread main
'Unconfined': After delay in thread kotlinx.coroutines.DefaultExecutor
'coroutineContext': After delay in thread main
*/
线程间切换
fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
fun main(args: Array<String>) {
newSingleThreadContext("Ctx1").use { ctx1 ->
newSingleThreadContext("Ctx2").use { ctx2 ->
runBlocking(ctx1) {
log("Started in ctx1")
run(ctx2) {
log("Working in ctx2")
}
log("Back to ctx1")
}
}
}
}
/*
[Ctx1 @coroutine#1] Started in ctx1
[Ctx2 @coroutine#1] Working in ctx2
[Ctx1 @coroutine#1] Back to ctx1*/
上下文中的Job
这里还真没看懂
fun main(args: Array<String>) = runBlocking<Unit> {
println("My job is ${coroutineContext[Job]}")
}
//My job is "coroutine#1":BlockingCoroutine{Active}@6d311334
协程的子协程
fun main(args: Array<String>) = runBlocking<Unit> {
// launch a coroutine to process some kind of incoming request
val request = launch {
//这个独立的子协程会继续工作,独立于父协程
val job1 = launch {
println("job1: I have my own context and execute independently!")
delay(1000)
println("job1: I am not affected by cancellation of the request")
}
//子协程继承父协程的上下文,则会随着父协程的取消而取消
val job2 = launch(coroutineContext) {
println("job2: I am a child of the request coroutine")
delay(1000)
println("job2: I will not execute this line if my parent request is cancelled")
}
// 父协程等待子协程完成任务
job1.join()
job2.join()
}
delay(500)
request.cancel() // 取消父协程
delay(1000)
println("main: Who has survived request cancellation?")
}
合并上下文
合并上下文后的原上下文的协程会被取消
fun main(args: Array<String>) = runBlocking<Unit> {
val request = launch(coroutineContext) { // use the context of `runBlocking`// spawns CPU-intensive child job in CommonPool !!!val job = launch(coroutineContext + CommonPool) {
println("job: I am a child of the request coroutine, but with a different dispatcher")
delay(1000)
println("job: I will not execute this line if my parent request is cancelled")
}
job.join() // request completes when its sub-job completes
}
delay(500)
request.cancel() // cancel processing of the request
delay(1000) // delay a second to see what happens
println("main: Who has survived request cancellation?")
}
/*
job: I am a child of the request coroutine, but with a different dispatcher
main: Who has survived request cancellation?
*/
父协程会等待子协程
fun main(args: Array<String>) = runBlocking<Unit> {
// launch a coroutine to process some kind of incoming requestval request = launch {
repeat(3) { i -> // launch a few children jobs
launch(coroutineContext) {
delay((i + 1) * 200L) // variable delay 200ms, 400ms, 600ms
println("Coroutine $i is done")
}
}
println("request: I'm done and I don't explicitly join my children that are still active")
}
request.join() // wait for completion of the request, including all its children
println("Now processing of the request is complete")
}
/*
request: I'm doneand I don't explicitly join my children that are still active
Coroutine 0 is done
Coroutine 1 is done
Coroutine 2 is done
Now processing of the request is complete
*/
给协程命名:CoroutineName
fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
fun main(args: Array<String>) = runBlocking(CoroutineName("main")) {
log("Started main coroutine")
// run two background value computations
val v1 = async(CoroutineName("v1coroutine")) {
delay(500)
log("Computing v1")
252
}
val v2 = async(CoroutineName("v2coroutine")) {
delay(1000)
log("Computing v2")
6
}
log("The answer for v1 / v2 = ${v1.await() / v2.await()}")
}
/*
[main @main#1] Started main coroutine
[ForkJoinPool.commonPool-worker-1@v1coroutine#2] Computing v1
[ForkJoinPool.commonPool-worker-2@v2coroutine#3] Computing v2
[main @main#1] The answer for v1 / v2 = 42*/
使用显性的Job来管理子协程
fun main(args: Array<String>) = runBlocking<Unit> {
val job = Job() // create a job object to manage our lifecycle
// now launch ten coroutines for a demo, each working for a different time
val coroutines = List(10) { i ->
// they are all children of our job object
launch(coroutineContext + job) { // we use the context of main runBlocking thread, but with our own job object
delay((i + 1) * 200L) // variable delay 200ms, 400ms, ... etc
println("Coroutine $i is done")
}
}
println("Launched ${coroutines.size} coroutines")
delay(500L) // delay for half a second
println("Cancelling the job!")
job.cancelAndJoin() // cancel all our coroutines andwaitfor all of them to complete
}
/*
Launched 10 coroutines
Coroutine 0 is done
Coroutine 1 is done
Cancelling the job!
*/