android Kotlin原理

news/2025/3/26 21:55:59/

目录

一,概述

kotlin%E5%8D%8F%E7%A8%8B%E5%BA%8F%E5%8E%9F%E7%90%86%3A-toc" name="tableOfContents" style="margin-left:40px">1.1 kotlin协程序原理:

 1.2 核心概念

二,协程调度器之Dispatchers

三,协程能进行线程恢复的原理


一,概述

kotlin%E5%8D%8F%E7%A8%8B%E5%BA%8F%E5%8E%9F%E7%90%86%3A" name="1.1%20kotlin%E5%8D%8F%E7%A8%8B%E5%BA%8F%E5%8E%9F%E7%90%86%3A">1.1 kotlin协程序原理:

1,内部线程池管理线程使用到了自旋和挂起

2,传统的线程之所以重,是因为线程的执行,等待唤醒需要操作系统来完成

3,协程之所以相对于传统的线程轻量级,是因为协程是通过协程调度器来完成

线程的唤醒,调度,执行的,区别就在哪里

4,协程是基于线程的,没有线程就没有协程,协程最终是通过开启线程,thread,调用

thread的start方法完成协程的调度的

协程是一种并发设计模式,您可以在 Android 平台上使用它来简化异步执行的代码。协程 是在 1.3 版中添加到 Kotlin 的,基于既定的 从其他语言转换成的概念。

在 Android 上,协程有助于管理长时间运行的任务,如果管理不当,这些任务可能会阻塞主线程并导致应用无响应。使用协程的专业开发者中有超过 50% 的人反映使用协程提高了工作效率。本主题介绍如何使用 Kotlin 协程解决以下问题,从而让您能够编写出更清晰、更简洁的应用代码。

 

协程是我们在 Android 上进行异步编程的推荐解决方案。值得关注的特点包括:

  • 轻量:您可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
  • 内存泄漏更少:使用 结构化并发 在一个范围内运行多项操作
  • 内置取消支持: 取消 通过正在运行的协程层次结构自动传播。
  • Jetpack 集成:许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可供您用于结构化并发。

1.2 核心概念

以上代码就涉及到了协程的四个基础概念:

  • suspend function。即挂起函数,delay() 就是协程库提供的一个用于实现非阻塞式延时的挂起函数
  • CoroutineScope。即协程作用域,GlobalScope 是 CoroutineScope 的一个实现类,用于指定协程的作用范围,可用于管理多个协程的生命周期,所有协程都需要通过 CoroutineScope 来启动
  • CoroutineContext。即协程上下文,包含多种类型的配置参数。Dispatchers.IO 就是 CoroutineContext 这个抽象概念的一种实现,用于指定协程的运行载体,即用于指定协程要运行在哪类线程上
  • CoroutineBuilder。即协程构建器,协程在 CoroutineScope 的上下文中通过 launch、async 等协程构建器来进行声明并启动。launch、async 均被声明为 CoroutineScope 的扩展方法

 1.3 kotlin协程调试办法

设置VM参数:-Dkotlinx.coroutines.debug

Android工程中打开协程debug模式,无法直接在工程中进行设置,而是需要在Android代码中设置相应属性。设置代码如下:

System.setProperty("kotlinx.coroutines.debug", "on" )

上面的对kotlin版本有要求,最好1.4以上

二,协程调度器之Dispatchers

三,协程能进行线程恢复的原理

kotlinx.coroutines.CoroutineContextKt

restoreThreadContext

这里是最核心的,这段代码是在Thread的run方法中被调用,在开始调用之前调用updateThreadContext(context, countOrElement)方法把当前线程的数据保存起来,然后在调用业务的 block函数,这里的context, countOrElement这两个参数是调用线程的数据和上下文(比如说在主线程中调用,那么这个数据就是主线程的),然后在block函数执行完成以后,在finally {
        restoreThreadContext(context, oldValue)
    }

调用restoreThreadContext(context, oldValue) 也就是恢复之前的数据,在这里完成了线程的数据切换(线程栈数据切换,保存的是线程堆栈信息)

internal fun updateThreadContext(context: CoroutineContext, countOrElement: Any?): Any? {@Suppress("NAME_SHADOWING")val countOrElement = countOrElement ?: threadContextElements(context)@Suppress("IMPLICIT_BOXING_IN_IDENTITY_EQUALS")return when {countOrElement === 0 -> ZERO // very fast path when there are no active ThreadContextElements//    ^^^ identity comparison for speed, we know zero always has the same identitycountOrElement is Int -> {// slow path for multiple active ThreadContextElements, allocates ThreadState for multiple old valuescontext.fold(ThreadState(context, countOrElement), updateState)}else -> {// fast path for one ThreadContextElement (no allocations, no additional context scan)@Suppress("UNCHECKED_CAST")val element = countOrElement as ThreadContextElement<Any?>element.updateThreadContext(context)}}
}

这里面是最核心的部分,使用了ThreadLocal来存储不同线程的数据,这个才是最核心的部分,只有这样子,那么在在从线程挂起到恢复的时候,才知道调用栈地址以及数据

internal class ThreadLocalElement<T>(private val value: T,private val threadLocal: ThreadLocal<T>
) : ThreadContextElement<T> {override val key: CoroutineContext.Key<*> = ThreadLocalKey(threadLocal)override fun updateThreadContext(context: CoroutineContext): T {val oldState = threadLocal.get()threadLocal.set(value)return oldState}override fun restoreThreadContext(context: CoroutineContext, oldState: T) {threadLocal.set(oldState)}


http://www.ppmy.cn/news/1582938.html

相关文章

.gitignore使用指南

.gitignore使用指南 目录 什么是.gitignore为什么需要.gitignore如何创建.gitignore文件.gitignore文件的语法规则 忽略单个文件忽略目录忽略特定类型的文件不忽略特定文件或目录递归匹配 示例.gitignore文件注意事项更多特殊场景匹配规则 忽略多个特定后缀的文件忽略特定目录…

PHP If...Else 语句详解

PHP If...Else 语句详解 引言 PHP 是一种流行的服务器端脚本语言&#xff0c;常用于开发动态网站和应用程序。在 PHP 编程中&#xff0c;条件语句是编程逻辑的基础&#xff0c;其中 if...else 语句是最基本且最常用的条件语句之一。本文将详细介绍 PHP 的 if...else 语句&…

Spring6: 2 入门

2、 入门 2.1 环境要求 JDK&#xff1a;Java17&#xff08;Spring6要求JDK最低版本是Java17&#xff09; Maven&#xff1a;3.6 Spring&#xff1a;6.0.2 2.2、构建模块 1&#xff09;构建父模块spring6 在idea中&#xff0c;依次单击 File -> New -> Project -&g…

深入解析:Nginx+Keepalived实现双机热备架构

全文目录&#xff1a; 开篇语前言摘要概述什么是双机热备&#xff1f;为什么选择 Nginx Keepalived&#xff1f;本文目标 架构设计与原理架构示意图工作原理 环境准备系统与软件环境基础网络配置 实战&#xff1a;Nginx Keepalived 双机热备配置第一步&#xff1a;安装 Nginx…

特殊行车记录仪DAT视频丢失的恢复方法

行车记录仪是一种常见的车载记录仪&#xff0c;和常见的“小巧玲珑”的行车记录仪不同&#xff0c;一些特种车辆使用的记录仪的外观可以用“笨重”来形容。下边我们来看看特种车载行车记录仪删除文件后的恢复方法。 故障存储: 120GB存储设备/文件系统:exFAT /簇大小:128KB 故…

隔空打印,IPP,IPD,HP Jetdirect协议的区别(Mac添加打印机四种协议的区别)

‌隔空打印‌&#xff1a;隔空打印是一种通过Wi-Fi、USB和以太网络访问打印机的协议。使用隔空打印协议&#xff0c;用户可以无需下载或安装打印机软件即可使用支持该协议的打印机。支持隔空打印的打印机品牌包括Aurora、Brother、Canon、Dell、Epson、Fuji、Hewlett Packard、…

嵌入式八股,为什么单片机中不使用malloc函数

1. 资源限制 单片机的内存资源通常非常有限&#xff0c;尤其是RAM的大小可能只有几KB到几十KB。在这种情况下&#xff0c;使用 malloc 进行动态内存分配可能会导致内存碎片化&#xff0c;使得程序在运行过程中逐渐耗尽可用内存。 2. 内存碎片问题 malloc 函数在分配和释放内…

leetcode-回文类题-647-求字符串中 回文子串 的数目

1、回文子串-647 题目&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 示例 1&#xff1a; 输入&#xff1a;s "abc"…