阿里P7大佬教你Kotlin协程实现原理:挂起与恢复

Kotlin协程:挂起与恢复原理逆向刨析 前言:只有在那崎岖的小路上不畏艰险奋勇攀登的人,才有希望达到光辉的顶点。经过前面两篇协程的学习,我相信大家对协程的使用已经非常熟悉了。本着知其然更要知其之所以然的心态,很想知道它里面是怎么可以让异步代码同步化的?协程它是如何实现线程的调度的?协程的挂起和恢复本质是什么?今天在这里一一为大家解答。整个Kotlin 协程学习分为三部曲,本文是第三篇:Kotlin 协程实战进阶(一、筑基篇)Kotlin 协程实战进阶(二、进阶篇)Kotlin 协程实战进阶(三、原理篇)(本文需要前面两篇文章协程的知识点作为基础) 阅读详情

Kotlin协程实现原理

今天我们来聊聊Kotlin的协程Coroutine。

如果你已经接触过协程,相信你都有过以下几个疑问:

  1. 协程到底是个什么东西?
  2. 协程的suspend有什么作用,工作原理是怎样的?
  3. 协程中的一些关键名称(例如:Job、Coroutine、Dispatcher、CoroutineContext与CoroutineScope)它们之间到底是怎么样的关系?
  4. 协程的所谓非阻塞式挂起与恢复又是什么?
  5. 协程的内部实现原理是怎么样的?
  6. …

接下来的一些文章试着来分析一下这些疑问,也欢迎大家一起加入来讨论。

挂起

协程是使用非阻塞式挂起的方式来保证协程运行的。那么什么是非阻塞式挂起呢?下面我们来聊聊挂起到底是一个怎样的操作。

在之前的文章中提及到suspend关键字,它的一个作用是代码调用的时候会为方法添加一个Continuation类型的参数,保证协程中Continuaton的上下传递。

而它另一个关键作用是起到挂起协程的标识。

协程运行的时候每遇到被suspend修饰的方法时,都有可能会挂起当前的协程。

注意是有可能。

你可以随便写一个方法,该方法也可以被suspend修饰,但这种方法在协程中调用是不会被挂起的。例如

private suspend fun a() {
 println("aa")
}

lifecycleScope.launch {
 a()
}

因为这种方法是不会返回COROUTINE_SUSPENDED类型的。

协程被挂起的标志是对应的状态下返回COROUTINE_SUSPENDED标识。

更深入一点的话就涉及到状态机。协程内部是使用状态机来管理协程的各个挂起点。

文字有点抽象,具体我们还是来看代码。我们就拿上面的a方法例子来说明。

首先在Android Studio打开这段代码的Kotlin Bytecode。可以在Tools -> Kotlin -> Show Kotlin Bytecode中打开。

然后点击其中的Decompile选项,生成对应的反编译java代码。最终代码如下:

BuildersKt.launch$default((CoroutineScope)LifecycleOwnerKt.getLifecycleScope(this), (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
   private CoroutineScope p$;
   Object L$0;
   int label;
 
   @Nullable
   public final Object invokeSuspend(@NotNull Object $result) {
      // 挂起标识
      Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
      CoroutineScope $this$launch;
      switch(this.label) {
      case 0:
         ResultKt.throwOnFailure($result);
         $this$launch = this.p$;
         MainActivity var10000 = MainActivity.this;
         // 保存现场
         this.L$0 = $this$launch;
         // 设置挂起后恢复时,进入的状态
         this.label = 1;
         // 判断是否挂起
         if (var10000.a(this) == var3) {
            // 挂起,跳出该方法
            return var3;
         }
         // 不需要挂起,协程继续执行其他逻辑
         break;
      case 1:
         // 恢复现场
         $this$launch = (CoroutineScope)this.L$0;
         // 是否需要抛出异常
         ResultKt.throwOnFailure($result);
         break;
      default:
         throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
      }

      return Unit.INSTANCE;
   }
 
   @NotNull
   public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
      Intrinsics.checkParameterIsNotNull(completion, "completion");
      Function2 var3 = new <anonymous constructor>(completion);
      var3.p$ = (CoroutineScope)value;
      return var3;
   }
 
   public final Object invoke(Object var1, Object var2) {
      return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
   }
}), 3, (Object)null);

上面的代码就是协程的状态机,通过label来代表不同的状态,从而对应执行不同case中的逻辑代码。

在之前的文章中已经介绍过,协程启动的时候会手动调用一次resumeWith方法,而它对应的内部逻辑就是执行上面的invokeSuspend方法。

所以首次运行协程时label值为0,进入case 0:语句。此时会记录现场为可能被挂起的状态做准备,并设置下一个可能被执行的状态。

如果a方法的返回值为var3,这个var3对应的就是COROUTINE_SUSPENDED。所以只有当a方法返回COROUTINE_SUSPENDED时才会执行if内部语句,跳出方法,此时协程就被挂起。当前线程也就可以执行其它的逻辑,并不会被协程的挂起所阻塞。

所以协程的挂起在代码层面来说就是跳出协程执行的方法体,或者说跳出协程当前状态机下的对应状态,然后等待下一个状态来临时在进行执行。

那为什么说我们写的这个a方法不会被挂起呢?

@Nullable
final Object a(@NotNull Continuation $completion) {
   return Unit.INSTANCE;
}

原来是它的返回值并不是COROUTINE_SUSPENDED。

既然它不会被挂起,那么什么情况下的方法才会被挂起呢?

很简单,如果我们在a方法中加入delay方法,它就会被挂起。

@Nullable
final Object a(@NotNull Continuation $completion) {
   Object var10000 = DelayKt.delay(1000L, $completion);
   return var10000 == IntrinsicsKt.getCOROUTINE_SUSPENDED() ? var10000 : Unit.INSTANCE;
}

真正触发挂起的是delay方法,因为delay方法会创建自己Continuation,同时内部调用getResult方法。

 internal fun getResult(): Any? {
     installParentCancellationHandler()
     if (trySuspend()) return COROUTINE_SUSPENDED
     // otherwise, onCompletionInternal was already invoked & invoked tryResume, and the result is in the state
     val state = this.state
     if (state is CompletedExceptionally) throw recoverStackTrace(state.cause, this)
     return getSuccessfulResult(state)
 }

在getResult方法中会通过trySuspend来判断挂起当前协程。由挂起自身的协程,从而触发挂起父类的协程。

如果只是为了测试,可以让a方法直接返回COROUTINE_SUSPENDED

 private suspend fun a(): Any {
     return kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
 }

当然线上千万不能这样写,因为一旦这样写协程将一直被挂起,因为你没有将其恢复的能力。

恢复

现在我们再来聊一聊协程的恢复。

协程的恢复本质是通过Continuation的resumeWith方法来触发的。

下面我们来看一个可以挂起的例子,通过它来分析协程挂起与恢复的整个流程。

println("main start")
lifecycleScope.launch {
   println("async start")
   val b = async {
       delay(2000)
       "async"
   }
   b.await()
   println("async end")
}
Handler().postDelayed({
   println("main end")
}, 1000)

Kotlin代码很简单,当前协程运行与主线程中,内部执行一个async方法,通过await方法触发协程的挂起。

再来看它的对应反编译java代码

// 1
String var2 = "main start";
System.out.println(var2);
BuildersKt.launch$default((CoroutineScope)LifecycleOwnerKt.getLifecycleScope(this), (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
   private CoroutineScope p$;
   Object L$0;
   Object L$1;
   int label;
 
   @Nullable
   public final Object invokeSuspend(@NotNull Object $result) {
      Object var5 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
      CoroutineScope $this$launch;
      Deferred b;
      switch(this.label) {
      case 0:
         // 2
         ResultKt.throwOnFailure($result);
         $this$launch = this.p$;
         String var6 = "async start";
         System.out.println(var6);
         b = BuildersKt.async$default($this$launch, (CoroutineContext)null, (CoroutineStart)null, (Function2)(new Function2((Continuation)null) {
            private CoroutineScope p$;
            Object L$0;
            int label;
 
            @Nullable
            public final Object invokeSuspend(@NotNull Object $result) {
               Object var3 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
               CoroutineScope $this$async;
               switch(this.label) {
               case 0:
                  // 3
                  ResultKt.throwOnFailure($result);
                  $this$async = this.p$;
                  this.L$0 = $this$async;
                  this.label = 1;
                  if (DelayKt.delay(2000L, this) == var3) {
                     return var3;
                  }
                  break;
               case 1:
                  // 5、6
                  $this$async = (CoroutineScope)this.L$0;
                  ResultKt.throwOnFailure($result);
                  break;
               default:
                  throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
               }
 
               return "async";
            }
 
            @NotNull
            public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
               Intrinsics.checkParameterIsNotNull(completion, "completion");
               Function2 var3 = new <anonymous constructor>(completion);
               var3.p$ = (CoroutineScope)value;
               return var3;
            }
 
            public final Object invoke(Object var1, Object var2) {
               return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
            }
         }), 3, (Object)null);
         this.L$0 = $this$launch;
         this.L$1 = b;
         this.label = 1;
         if (b.await(this) == var5) {
            return var5;
         }
         break;
      case 1:
         // 7
         b = (Deferred)this.L$1;
         $this$launch = (CoroutineScope)this.L$0;
         ResultKt.throwOnFailure($result);
         break;
      default:
         throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
      }
 
      // 8
      String var4 = "async end";
      System.out.println(var4);
      return Unit.INSTANCE;
   }
 
   @NotNull
   public final Continuation create(@Nullable Object value, @NotNull Continuation completion) {
      Intrinsics.checkParameterIsNotNull(completion, "completion");
      Function2 var3 = new <anonymous constructor>(completion);
      var3.p$ = (CoroutineScope)value;
      return var3;
   }
 
   public final Object invoke(Object var1, Object var2) {
      return ((<undefinedtype>)this.create(var1, (Continuation)var2)).invokeSuspend(Unit.INSTANCE);
   }
}), 3, (Object)null);
// 4
(new Handler()).postDelayed((Runnable)null.INSTANCE, 1000L);

有点长,没关系我们只看关键点,看它的状态机相关的内容。

  1. 首先会输出main start,然后通过launch创建协程,进入协程状态机,此时label为0,执行case: 0相关逻辑。
  2. 进入case: 0后输出**async start**,调用async并通过await来挂起当前协程,再挂起的过程中记录当前挂起点的数据,并将lable设置为1。
  3. 进入async创建的协程,此时async协程中的lable为0,进入async case: 0执行dealy并挂起async的协程。并将label设置为1。等待2s之后被唤醒。
  4. 此时协程都被挂起,即跳出协程launch方法,执行handler操作。由于post 1s所以比协程中dealy还短,所以会优先输出**main end**,然后再过1s,进入恢复协程阶段
  5. async中的协程被delay恢复,注意在delay方法中传入了this,async的Continuation对象,所以delay内部一旦完成2s计时就会调用Continuation的resumeWith方法来恢复async中的协程,即调用invokeSuspend方法。
  6. 由于被挂起之前已经将async label设置为1,所以进入case: 1,恢复之前挂起的现场,检查异常,最终返回async。
  7. 此时await挂起点被恢复,注意它也传入了this,对应的就是launch中的Continuation,所以也会回调resumeWith方法,最终调用invokeSuspend,即进入case 1:恢复现场,结束状态机。
  8. 最后再继续输出async end,协程运行结束。

我们可以执行上面的代码来验证输出是否正确

main start
async start
main end
async end

我们来总结一下,协程通过suspend来标识挂起点,但真正的挂起点还需要通过是否返回COROUTINE_SUSPENDED来判断,而代码体现是通过状态机来处理协程的挂起与恢复。在需要挂起的时候,先保留现场与设置下一个状态点,然后再通过退出方法的方式来挂起协程。在挂起的过程中并不会阻塞当前的线程。对应的恢复通过resumeWith来进入状态机的下一个状态,同时在进入下一个状态时会恢复之前挂起的现场。

本篇文章主要介绍了协程的挂起与恢复原理,同时也分析了协程的状态机相关的执行过程。希望对学习协程的伙伴们能够有所帮助,敬请期待后续的协程分析。

需要更多的Kotlin学习资料可以扫码免费领取!

《史上最详Android版kotlin协程入门进阶实战 》

第一章 Kotlin协程的基础介绍

​ ● 协程是什么

​ ● 什么是Job 、Deferred 、协程作用域

​ ● Kotlin协程的基础用法

img

第二章 kotlin协程的关键知识点初步讲解

​ ● 协程调度器

​ ● 协程上下文

​ ● 协程启动模式

​ ● 协程作用域

​ ● 挂起函数

img

第三章 kotlin协程的异常处理

​ ● 协程异常的产生流程

​ ● 协程的异常处理

img

第四章 kotlin协程在Android中的基础应用

2024阿里Android面经深度解析:高频考点与实战指南 在移动开发领域,进程间通信(IPC)是构建复杂、高性能应用的核心技术之一,其原理直接关系到应用的性能与稳定性。Android系统基于Linux内核,却创新性地采用了Binder机制作为其主要的IPC方案,这背后是出于对性能、安全性和面向对象编程范式的综合考量。Binder通过一次拷贝和基于引用的安全模型,在效率与安全性之间取得了平衡,成为连接应用层与系统服务、以及应用内部组件通信的基石。理解其从Proxy/Stub到Binder驱动的完整流程,是深入掌握Android Framework层的关键。这项技术的 阅读详情

相关推荐

【信息科学与工程学】计算机科学与自动化——第三百零四篇 高性能系统开发指南01

高并发:限流、熔断、降级高性能:红包拆分、多级缓存、大Key/热Key拆分、Pipeline、线程池、RocketMQ零丢失、幂等、分布式锁、集群缩容、分批入库海量数据处理:日志分表分片、跨表查询、冷热分层、大数据引擎服务器选型系统安全:网关安全、服务器安全、云存储安全、风控、监控、测试数据一致性:缓存与数据库一致性、大厂方案、蓝绿回滚、流量一致性、流程一致性项目与团队管理:流程问题、管理问题(风险、成本、人员、文档、培训)稳定性建设:上线三板斧、线上五步闭环、混沌工程、容量规划。

weixin_49199313的博客 251

Kotlin 以3秒后退出应用为例,用handler+postDelayed() 实现倒计时

1、初始化三个属性 private var mTime = 3 private var mHandler: Handler = Handler() private val mRunnable: Runnable = object : Runnable { override fun run() { // TODO: 倒计时逻辑 ...

ihoudf 5800

Qt (高仿Visio)流程图组件开发(一) 效果展示及基本开发框架构思

最近因为工作原因需要使用Qt开发一个类似于Visio的流程图组件,需满足基本的流程图功能,图元类型可自定义扩展,不同图元存有各类自定义数据,可以保存为xml文件,可以读取xml文件生成流程图等等。

qq_43793182的博客 1万+

[kotlin]处理延时操作

在 Kotlin 中处理延迟操作可以通过多种方式实现,每种方式都适用于不同的场景和需求。

Gamin 3635

类银河恶魔城学习记录1-1 Player状态机的搭建 P28

什么是状态机?一篇文章就够了 - 知乎说实话,目前并不能深入理解状态机的奇妙之处(当然,我觉得状态机作为教程的重要组成部分是不得不理解的,所以以下我会对游戏教程内的状态机做一些我认为的解释,如有错误,请多包涵)

Homura_的博客 2341

【具身算法】VLA算法-Diffusion Policy

《扩散策略:多模态机器人控制的新方法》摘要 本文提出了一种基于扩散模型的机器人控制策略(DiffusionPolicy),用于解决视觉运动控制中的多模态行为、高维动作空间和训练稳定性问题。该方法利用去噪扩散概率模型(DDPM)生成动作序列,通过迭代优化处理复杂动作分布,显著提升了性能。实验表明,在15项机器人操作任务中,扩散策略平均性能提升46.9%,有效解决了传统显式/隐式策略的局限性。其核心优势在于:1)优雅建模多模态动作分布;2)适应高维动作空间;3)训练过程稳定。未来工作将探索与强化学习的结合及计算

puzhinan7781的博客 1391

Kotlin协程到底是怎么切换线程的?你是否知晓?

好文推荐: 作者:RicardoMJiang 前言 之前对协程做了一个简单的介绍,回答了协程到底是什么的问题,感兴趣的同学可以了解下:【带着问题学】协程到底是什么? 通过上文,我们了解了以下内容 1.kotlin协程本质上对线程池的封装 2.kotlin协程可以用同步方式写异步代码,自动实现对线程切换的管理 这就引出了本文的主要内容,kotlin协程到底是怎么切换线程的? 具体内容如下: 1. 前置知识 1.1 CoroutineScope到底是什么? CoroutineScope即协程运行的作用域,.

鸿蒙开发知识记录 4286

Matlab实战:用卡尔曼滤波搞定无人机GPS轨迹优化(附完整代码)

本文详细介绍了如何使用Matlab实现卡尔曼滤波(KF)算法优化无人机GPS轨迹,提供完整代码和工程实践指南。通过线性卡尔曼滤波技术,有效降低定位噪声,提升轨迹平滑度,适用于无人机导航和控制系统开发。

weixin_29061425的博客 253

Kotlin中实现简单的倒计时按钮

在kotlin中实现最简单的有倒计时功能的按钮,诸如注册时需要点击获取验证码,点击后直接变成倒计时状态。 /** * 创建时间: 2018/12/26 0026 * 创建人:ldm * 功能描述: */ class CountdownButton(mContext: Context, attrSet: AttributeSet) : Button(mContext, attrSet) { ...

true100的专栏 9772

SoC低功耗设计实战:28nm工艺下四核A7的Hierarchical Flow全流程解析

本文深入解析了在TSMC 28nm工艺上,采用Hierarchical Flow(层次化流程)实现四核Cortex-A7 SoC低功耗设计的全流程。文章从项目背景切入,详细探讨了基于UPF的电源规划、时钟树综合、接口时序收敛以及物理验证等关键环节,分享了使用Cadence Innovus等工具进行低功耗物理实现的实战经验与挑战。

weixin_29231263的博客 325

Spring 核心技术解析【纯干货版】- I:Spring 基础模块 Spring-Core 模块精讲

Spring-Core 模块,是 Spring 核心容器模块之一。虽然 “Core” 本身就有 “核心的,重要的部分” 的含义,但是它并非是实现(常被我们说为 Spring 核心机制)IOC / AOP 的模块。Spring 中的 IOC 机制,主要来自于 BeanFactory 容器和 ApplicationContext 容器,这二者分别由同为核心容器模块的 Spring-Bean 模块 和 Spring-Context 模块所提供。

栗筝i的博客 2525

阿里P7大佬教你破解 Kotlin 协程(6) - 协程挂起篇

​ ● 协程是什么​ ● 什么是Job 、Deferred 、协程作用域​ ● Kotlin协程的基础用法。

Android_XG的博客 268

GitLab CI/CD .gitlab-ci.yml 关键词(十一):发布版本 release

本篇文章介绍使用GitLab CI/CD 发布一个版本,对外发布。并填写一些发布的信息。

知无涯 4723

最新Kotlin:深度理解协程挂起恢复实现原理。纯源码分析。(1),2024年最新阿里p7升p8 晋升面试

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:架构师筑基必备技能Android框架体系架构(高级UI+FrameWork源码)360°Androidapp全方位性能调优设计思想解读开源框架NDK模块开发移动架构师专题项目实战环节移动架构师不可不学习微信小程序混合开发的flutterAndroid学习的资料我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。

2401_84561579的博客 1007

CMake入门教程【基础篇】在Windows、Linux上安装CMake

CMake如何下载与安装

小鱼酱的博客 2727

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Kotlin(九,阿里P7大牛亲自教你

| join() | 等待协程执行完毕 | | cancel() | 取消一个协程 | 协程的启动 public fun CoroutineScope.launch( context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job{ val new

m0_61418455的博客 220

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

kotlin协程入门、进阶和实战三大部分,Android开发应该怎么学?_kotlin协程学习路线

协程是什么什么是Job 、Deferred 、协程作用域Kotlin协程的基础用法。

2401_84164469的博客 579

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

最全Android Kotlin入门教程(Kotlin 入门指南、高级Kotlin强化实战、Kotlin协程进阶实战)

Kotlin 是一种新型的静态类型编程语言,有超过 60% 的专业 Android 开发者在使用,它有助于提高工作效率、开发者满意度和代码安全性。不仅可以减少常见代码错误,还可以轻松集成到现有应用中。目前在安卓开发中,当你查看源码的时候,你会发现大量的Kotlin 源码,在使用一些 jetpack 框架的时候,大部分也都是Kotlin 语言。相信不久之后,Kotlin 将会成为 Android 开发的首选语言。

datian1234的博客 1286

kotlin协程详解,不可能学不懂,HarmonyOS鸿蒙大厂高级面试题灵魂100问

阻塞很简单,就是字面意思,在 Android 中的体现,其实就是阻塞了主线程的运行,那么非阻塞就是没有卡住主线程的运行挂起就是保存当前状态,等待恢复执行,在 Android 中的体现,挂起就是不影响主线程的工作,更贴切的说法可以理解为切换到了一个指定的线程,通过上面概念的解释,非阻塞式挂起就是不会卡住主线程且将程序切换到另外一个指定的线程去执行协程,英文名 Coroutine,源自 Simula 和 Modula-2 语言,它是一种协作式多任务实现,是一种编程思想,并不局限于特定的语言。

2301_82243558的博客 1040

kotlin协程入门、进阶和实战三大部分,Android开发应该怎么学?_kotlin协程学习路线(1)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!因此收集整理了一份《2024年最新HarmonyOS鸿蒙全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。 既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上鸿蒙开发知识点,真正体系化!由于文件比较多,这里只是将部分目录截图出来,

2401_84164469的博客 992

kotlin协程详解,不可能学不懂(2),近期有面试的必看

1)、并发就是同一时刻只有一条指令在执行,但是因为 CPU 时间片非常的小,多个指令间能够快速的切换,使得我们看起来拥有同时执行的效果,存在于单核或多核 CPU 系统中2)、并行就是同一时刻有多条指令同时在执行,存在于多核 CPU 系统中举个生活中人吃馒头的例子:一个人买了 3 个馒头,那么他同一时刻只能在吃一个馒头,这是并发。而 3 个人每人买了一个馒头,那么同一时刻他们能同时吃馒头,这是并行。并发和并行的区别在于同一时刻是否在同时进行。

2401_84164503的博客 794

JVM 常见面试问答:深入底层原理

本文为Java后端开发、架构师及中间件开发岗位面试提供全面的JVM知识体系,涵盖内存模型、对象创建、类加载、垃圾回收、JIT编译、性能调优等核心内容。内容分为14个章节,从基础概念到高级场景实战,包括: JVM内存模型:程序计数器、虚拟机栈、堆、方法区等运行时数据区详解。 对象创建与内存分配:对象实例化过程、TLAB机制、逃逸分析等。 类加载机制:双亲委派模型、类加载阶段、自定义类加载器。 垃圾回收:分代回收算法、CMS/G1/ZGC等回收器对比与原理。

weixin_72753562的博客 1017

【AI Agent】2026年9月 AI Agent 全栈开发最新技术面试宝典(含高频+必背+大厂真题)

本文整理了2026年AI Agent全栈开发最新技术面试题,涵盖基础概念、核心框架和系统设计等关键领域。重点解析了AI Agent与普通Chatbot的本质区别(自主闭环执行能力)、Agentic Loop的完整工作流程(规划-执行-观察-评估循环),以及ReAct范式的原理与适用场景。特别强调面试回答技巧:需结合工程实践中的典型问题、处理方案和量化指标,而非简单背诵定义。内容来自字节、阿里等大厂真实面经,适合3-5年经验开发者准备春招面试,突出考察候选人在复杂场景下的技术决策能力。

小江的记录本 4621

工作中使用到的单词(软件开发)

1.エイリアス   alias 别名 powershell使用 get-help 命令时,会得到与此命令 相关(别名)的命令 2.プロキシ proxy 代 理 3.プロモート   promote 促进,提升   开发的系统新功能上线发布,有时会使用到这个词,比如 STプロモート 还有使用リリース这个词的。比如STリリース。个人认为两者含义相同。 4.見逃し み................................................................

sun0322 6万+

【中级—,kotlin教程

public class User { private String password; private String username; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUs

flunsna的博客 327

【Android】kotlin协程挂起、恢复原理

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

m0_64365896的博客 1951
上一篇: Android音视频不愁字节跳动、腾讯、阿里进不去
下一篇: 在华为OD的程序员经验分享
不秃头de程序猿
博客等级 码龄5年 4089粉丝 1478原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值