IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 【Kotlin】协程 -> 正文阅读

[移动开发]【Kotlin】协程

1,概述

协程是一个轻量级的线程,将调度从系统线程切换拿到用户态,在一定程度上减少了线程切换开销。

2,简单实例

导入依赖:

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2"
}

(1)基本使用

//主协程
fun main() = runBlocking {

    //开启一个新协程
    val job = launch {
        delay(1000)
        println("task-1")
    }

    println("task-0")
    job.join()//等待job执行完毕,如果此处不join,会退出主协程
}

(2)开启多个协程

 //开启10万次,
    repeat(100_000){
        launch { 
            println("task-t")
        }
    }

(3)async

//定义挂机函数suspend,此定义后可以运行在协程中
suspend fun task1(): Int {
    delay(200)
    return 0
}

suspend fun task2(): Int {
    delay(300)
    return 1
}


//主协程
fun main() = runBlocking {

    val result1 = async { task1() }
    val result2 = async { task2() }
    println("wait task result: ${result1.await()} ${result2.await()}")

}

(4)withContext

//主协程
fun main() = runBlocking {

    //指定协程运行的线程,
    //Main IO Default Unconfined 四个默认值
    withContext(Dispatchers.Unconfined) {
        println("Unconfined Dispatchers")
    }

}

(5)协程回调

job.invokeOnCompletion {
        println("task-1 done!")
    }

3,协程通信

(1)channel

suspend fun main(){
    val channel = Channel<Int>()

    val producer = GlobalScope.launch {
        var i = 0
        while (true){
            delay(100)
            channel.send(i++)
        }
    }

    val consumer = GlobalScope.launch {
        while (true){
            println(channel.receive())
        }
    }

    producer.join()
    consumer.join()
}

上述代码中构造了两个协程producer和consumer,由于没有为它们明确指定调度器,所以它们的调度器都是默认的,在Java平台上就是基于线程池实现的Default。它们可以运行在不同的线程上,也可以运行在同一个线程上。

?(2)channel迭代

下例中,iterator.hasNext()是挂起函数,在判断是否有下一个元素的时候就需要去Channel中读取元素了。

suspend fun main() {
    val channel = Channel<Int>()

    val producer = GlobalScope.launch {
        var i = 0
        while (i <= 5) {
            delay(100)

            println("send before")
            channel.send(i++)
            println("send after")

        }
        //关闭通道
        channel.close()
    }

    val consumer = GlobalScope.launch {
        val iterator = channel.iterator()
        while (iterator.hasNext()) {
            println(iterator.next())
        }

        println("exit consumer")
    }

    producer.join()
    consumer.join()
}

send、receiver也是挂起函数,可以通过输出了解,

send before
send after
0
send before
send after
1
send before
send after
2
send before
send after
3
send before
send after
4
send before
send after
5
exit consumer

(3)生产-消费API[实验阶段]

suspend fun main() {
    //创建生产者
    val receiveChannel: ReceiveChannel<Int> = GlobalScope.produce {
        repeat(5) {
            delay(100)
            send(1)
        }
    }

    //接收数据
    GlobalScope.launch {
        val iterator = receiveChannel.iterator()
        while (iterator.hasNext()) {
            println(iterator.next())
        }
    }

    //创建消费者
    val sendChannel: SendChannel<Int> = GlobalScope.actor {
        while (true) {
            println(receive())
        }
    }
    // 发生数据
    sendChannel.send(0)
}

(4)BroadcastChannel

发送端和接收端在Channel中存在一对多的情形,从数据处理本身来讲,虽然有多个接收端,但是同一个元素只会被一个接收端读到。广播则不然,多个接收端不存在互斥行为。

suspend fun main() {

    val broadcastChannel = BroadcastChannel<Int>(Channel.BUFFERED)

    GlobalScope.launch {
        List(3) {
            delay(100)
            broadcastChannel.send(it)
        }
        broadcastChannel.close()
    }

    List(3) {
        GlobalScope.launch {
            //订阅该广播channel
            val receiveChannel = broadcastChannel.openSubscription()
            //下列for循环,是重写了iterator方法,实质是while循环逻辑
            //val iterator = iterator()
            //while (iterator.hasNext()) {
            //    println(iterator.next())
            //}
            for (i in receiveChannel) {
                println("[#$it] received: $i")
            }
        }
    }.joinAll()//创建的三个协程全部join
}

输出如下,三个协程输出无顺序,

[#1] received: 0
[#0] received: 0
[#2] received: 0
[#1] received: 1
[#2] received: 1
[#0] received: 1
[#1] received: 2
[#2] received: 2
[#0] received: 2

除了直接创建以外,我们也可以用前面定义的普通Channel进行转换

suspend fun main() {

    val channel = Channel<Int>()

    val broadcast = channel.broadcast(3)

    List(3) {
        GlobalScope.launch {
            delay(100) //注意,如果不delay,没有订阅者,send发送的信息会被丢弃
            broadcast.send(it)
        }
    }

    List(3){
        GlobalScope.launch {
            val receiveChannel = broadcast.openSubscription()
            for (i in receiveChannel) {
                println("[#$it] received: $i")
            }
        }
    }.joinAll()
}

(5)Flow

随着RxJava的流行,响应式编程模型逐步深入人心。Flow就是Kotlin协程与响应式编程模型结合的产物。

fun main() = runBlocking {

    val intFlow = flow<Int> {
        (1..3).forEach {
            emit(it)
            println("emit:" + Thread.currentThread().name)
            delay(100)
        }
    }

    GlobalScope.launch {
        // 手动设置调度器
        intFlow.flowOn(Dispatchers.IO).collect {
            println("Thread->${Thread.currentThread().name} $it")
        }
    }.join()
}

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:26:11  更:2022-03-03 16:27:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 16:58:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码