首页 > 其他分享 >kotlin的协程

kotlin的协程

时间:2022-11-21 07:55:25浏览次数:37  
标签:task1 task2 协程 Thread kotlin start println main

一、关于协程库的导入

1、使用下载包的方式

可以到该网站下载https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core对应的协程库

本地调试运行可以使用类似命令:kotlinc -classpath kotlinx-coroutines-core-1.2.2.jar -script coroutine.kts

 

2、使用gradle的方式

在build.gradle的dependencies中添加

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.2"

 

二、关于协程的使用

1、基础的语法

import kotlinx.coroutines.*

fun task1() {
    println("start task1 in Thread ${Thread.currentThread()}")
    println("end task1 in Thread ${Thread.currentThread()}")
}
fun task2() {
    println("start task2 in Thread ${Thread.currentThread()}")
    println("end task2 in Thread ${Thread.currentThread()}")
}
println("start")
runBlocking {
    task1()
    task2()
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

如上所示,在runBlocking中运行,假设当前的kts文件下面有一个对应的kotlinx-coroutines-core-1.2.2.jar,那么可以使用如下的命令运行

kotlinc -classpath kotlinx-coroutines-core-1.2.2.jar -script coroutine.kts

运行的结果为

start
start task1 in Thread Thread[main,5,main]
end task1 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]
call task1 and task2 in Thread Thread[main,5,main]

这个流程基本跟咱们顺序调用的一样,没看出协程的特点

如果我们的runBlocking使用如下那么可以看出一点区别

runBlocking {
    launch {task1()}
    launch {task2()}
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

结果如下
call task1 and task2 in Thread Thread[main,5,main]
start task1 in Thread Thread[main,5,main]
end task1 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]  
end task2 in Thread Thread[main,5,main]

可以看出使用launch进行调用,结果有一些不一样,如上黄底的结果先打印出来,再打印task1和task2

 

2、使用delay和yield为另外的刮起任务提供执行机会

注意:kotlin只允许带有suspend关键字的函数使用挂起点,所以使用delay和yield的时候,该函数需要标注suspend

import kotlinx.coroutines.*
suspend fun task1() {
    println("start task1 in Thread ${Thread.currentThread()}")
    yield()
    println("end task1 in Thread ${Thread.currentThread()}")
}
suspend fun task2() {
    println("start task2 in Thread ${Thread.currentThread()}")
    yield()
    println("end task2 in Thread ${Thread.currentThread()}")
}
println("start")
runBlocking {
    launch {task1()}
    launch {task2()}
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

如上所示因为task1和task2中包含yield函数,所以函数需要使用如上黄底的标志;上面的执行结果为

start
call task1 and task2 in Thread Thread[main,5,main]
start task1 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task1 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

3、显示设置上下文

在第二点中,虽然跑的都是多线程,但是我们发现他们都是在主线程中执行(同一个线程)

我们可以指定在哪个函数中运行

runBlocking {
    launch(Dispatchers.Default) {task1()}
    launch {task2()}
    println("call task1 and task2 in Thread ${Thread.currentThread()}")
}

如上所示,task1在不同的线程中运行,运行结果如下所示

start
start task1 in Thread Thread[DefaultDispatcher-worker-1,5,main]
end task1 in Thread Thread[DefaultDispatcher-worker-1,5,main]
call task1 and task2 in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

可以使用指定的线程池中的线程创建执行器

Executors.newSingleThreadExecutor().asCoroutineDispatcher().use {context ->
    println("start")
    runBlocking {
        launch(context) {task1()}
        launch {task2()}

        println("called task1 and task2 from Thread ${Thread.currentThread()}")
    }
}

1、创建执行器:Executors.newSingleThreadExecutor(); 需要导入包:import java.util.concurrent.Executors

2、使用kotlinx.coroutines库添加asCoroutineDispatcher() 从而获得一个CoroutineContext, 最后调用context

如上的显示结果

start
start task1 in Thread Thread[pool-1-thread-1,5,main]
end task1 in Thread Thread[pool-1-thread-1,5,main]
called task1 and task2 from Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

 

4、在挂起点切换线程

使用CoroutineContext和CoroutineStart参数来实现

launch有两个参数,第一个context是当前在那个context中运行,第二个start是该launch的运行机制

context:如果不设置,则在当前的线程中运行,如果有指定的context则在指定context中运行

start有

DEFAULT, ATOMIC, UNDISPATCHED,LAZY

DEFAULT:我们如果start不设置则默认为该参数,即在当前的上下文中运行

ATOMIC:如果该函数不允许被取消

LAZY:懒操作,使用该参数则会在遇到调用start才会开始运行:launch是start,async则是join或者await

UNDISPATCHED:刚开始使用当前的上下文中进行,如果遇到挂起点之后则会切换到其他线程:这个比较特殊,是实验性,则需要标注对应的实验性

Executors.newSingleThreadExecutor().asCoroutineDispatcher().use {context ->
    println("start")
    runBlocking {
        @OptIn(ExperimentalCoroutinesApi::class)
        launch(context = context, start = CoroutineStart.UNDISPATCHED) {task1()}
        launch {task2()}
        println("called task1 and task2 from Thread ${Thread.currentThread()}")
    }
}

如上的黄色标记所示,并且执行运行的时候要做特殊的标记-opt-in=kotlin.RequiresOptIn

整体运行命令:

kotlinc -opt-in=kotlin.RequiresOptIn -classpath kotlinx-coroutines-core-1.2.2.jar -script coroutine.kts

 

5、使用指定的上下文运行

runBlocking {
    println("starting in Thread ${Thread.currentThread()}")
    withContext(Dispatchers.Default) {task1()}
    launch{task2()}
    println("ending in Thread ${Thread.currentThread()}")
}

注意withContext没有启动新的协程,只是修改了当前执行的协程的上下文;运行结果如下所示

starting in Thread Thread[main,5,main]
start task1 in Thread Thread[DefaultDispatcher-worker-2,5,main]
end task1 in Thread Thread[DefaultDispatcher-worker-2,5,main]
ending in Thread Thread[main,5,main]
start task2 in Thread Thread[main,5,main]
end task2 in Thread Thread[main,5,main]

 

标签:task1,task2,协程,Thread,kotlin,start,println,main
From: https://www.cnblogs.com/czwlinux/p/16910228.html

相关文章

  • kotlin的suspend对比csharp的async&await
    协程的出现大大降低了异步编程的复杂度,可以让我们像写同步代码一样去写异步代码,如果没有它,那么很多异步的代码都是需要靠回调函数来一层层嵌套,这个在我之前的一篇有介绍......
  • 再探Kotlin 跨平台——迁移Paging分页库至KMM
    前言KMM的发展除了靠官方社区的支持外,一些大企业的开源落地也尤为重要。从这些开源中我们需要借鉴他的设计思想和实现方式。从而在落地遇到问题时,寻得更多的解决办法。上周,S......
  • Kotlin 起步
    https://kotlinlang.org/docs/getting-started.html起步Kotlin是一个现代化且成熟的编程语言,旨在使开发者更加快乐。它简洁,安全,可以与Java和其他编程语言相交互,同时......
  • python 协程学习笔记
    yield生成器frominspectimportgetgeneratorstatedefgen1():x=yield2print(x)y=yieldxreturnyg=gen1()print(getgeneratorstate(......
  • 协程
    协程:基本概念:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及......
  • 简易血槽残影设计方案(使用协程)
    今天看了段DNF视频,有发现到血条变化效果是这样的:  这里为了突出Boss受到的伤害之大,也就是玩家的伤害之高,以至于Boss的血条变化会出现残影效果。那么,就简......
  • kotlin的流畅性
    一、关于运算符的重载kotlin的运算符重载和c++的运算符重载比较类似,使用operator的方式:operatorfunxxx的方式比如重载类Complex的乘号dataclassComplex(valreal:......
  • python 多进程 多线程 协程
    多进程-进程池1fromconcurrent.futuresimportProcessPoolExecutor23withProcessPoolExecutor(max_workers=10)asexecutor:4results=executor.map......
  • Python用yield form 实现异步协程爬虫
    很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习。争取用看得懂的字来描述问题。1.什么是yield如果还没有怎么用过的话,直接把yield......
  • 又一巨头从 Java 迁移到 Kotlin,简直很无语。。
    出品|OSC开源社区(ID:oschina2013)Meta发布了一篇博客表示,正在将其Android应用的Java代码迁移到Kotlin,并分享了这一过程中的一些经验。该公司认为,Kotlin是一种流......