【Kotlin】协程的字节码原理

前言

协程是Koltin语言最重要的特性之一,也是最难理解的特性。网上关于kotlin协程的描述也是五花八门,有人说它是轻量级线程,有人说它是无阻塞式挂起,有人说它是一个异步框架等等,众说纷芸。甚至还有人出了书籍专门介绍kotlin协程。

笔者刚开始接触这个概念也是一头雾水:什么叫轻量级线程?难道它是一个操作系统级别的任务调度器吗?闻所未闻呀。

后来才知道协程它其实不是线程,它只是一个语言层面的东西,确切地讲它是一个轻量级的线程框架,主要功能是可以实现简洁的线程切换,避免了直接使用Thread导致的回调地狱。也可以说它用同步的方式实现异步操作。

看别人怎么介绍,还不如亲眼看一看协程的字节码,其实没那么难。

在这里插入图片描述
笔者原创,转载请注明来源:https://blog.csdn.net/devnn/article/details/135610313

协程字节码

在MainActivity的onCreate中写一段协程的代码:

lifecycleScope.launchWhenResumed {
      Log.i("MainActivity", "launchWhenResumed,isMainThread:${Thread.currentThread().id == Looper.getMainLooper().thread.id}")//这里打印true
      Log.i("MainActivity", "launchWhenResumed,threadId:${Thread.currentThread().id}")//这里threadId打印2也就是主线程
      //以下两个代码块是串行执行的
      withContext(Dispatchers.Main) {
          Thread.sleep(10000)
          Log.i("MainActivity", "launchWhenResumed,withContext1,threadId:${Thread.currentThread().id}")
      }
      withContext(Dispatchers.IO) {
          Log.i("MainActivity", "launchWhenResumed,withContext2,threadId:${Thread.currentThread().id}")
      }
 }

笔者用lifecycleScope创建了一个协程,用其它方式创建也是一样的,比如MainScope()、GlobalScope、viewModelScope等等,这些方式的区别不是本文介绍的重点。

以上代码的字节码内容如下:

 L33
    LINENUMBER 126 L33
    ALOAD 0
    CHECKCAST androidx/lifecycle/LifecycleOwner
    INVOKESTATIC androidx/lifecycle/LifecycleOwnerKt.getLifecycleScope (Landroidx/lifecycle/LifecycleOwner;)Landroidx/lifecycle/LifecycleCoroutineScope;
    NEW com/devnn/demo/MainActivity$onCreate$6
    DUP
    ACONST_NULL
    INVOKESPECIAL com/devnn/demo/MainActivity$onCreate$6.<init> (Lkotlin/coroutines/Continuation;)V
    CHECKCAST kotlin/jvm/functions/Function2
    INVOKEVIRTUAL androidx/lifecycle/LifecycleCoroutineScope.launchWhenResumed (Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/Job;
    POP

协程代码块被封装成了一个匿名内部类,匿名内部类继承了SuspendLambda(它实现了Continuation接口),同时实现了Function2接口,匿名内部类的构造方法需要一个Continuation参数,以上传null。

这个匿名内部类com/devnn/demo/MainActivity\$onCreate\$6.class内容如下:

final class com.devnn.demo.MainActivity$onCreate$6 extends kotlin.coroutines.jvm.internal.SuspendLambda implements kotlin.jvm.functions.Function2<kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<? super kotlin.Unit>, java.lang.Object> {
  int label;

  com.devnn.demo.MainActivity$onCreate$6(kotlin.coroutines.Continuation<? super com.devnn.demo.MainActivity$onCreate$6>);
    Code:
       0: aload_0
       1: iconst_2
       2: aload_1
       3: invokespecial #13                 // Method kotlin/coroutines/jvm/internal/SuspendLambda."<init>":(ILkotlin/coroutines/Continuation;)V
       6: return

  public final java.lang.Object invokeSuspend(java.lang.Object);
    Code:
       0: invokestatic  #39                 // Method kotlin/coroutines/intrinsics/IntrinsicsKt.getCOROUTINE_SUSPENDED:()Ljava/lang/Object;
       3: astore_2
       4: aload_0
       5: getfield      #43                 // Field label:I
       8: tableswitch   { // 0 to 2
                     0: 36
                     1: 134
                     2: 176
               default: 186
          }
      36: aload_1
      37: invokestatic  #49                 // Method kotlin/ResultKt.throwOnFailure:(Ljava/lang/Object;)V
      40: ldc           #51                 // String MainActivity
      42: ldc           #53                 // String launchWhenResumed,isMainThread:
      44: invokestatic  #59                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
      47: invokevirtual #63                 // Method java/lang/Thread.getId:()J
      50: invokestatic  #69                 // Method android/os/Looper.getMainLooper:()Landroid/os/Looper;
      53: invokevirtual #72                 // Method android/os/Looper.getThread:()Ljava/lang/Thread;
      56: invokevirtual #63                 // Method java/lang/Thread.getId:()J
      59: lcmp
      60: ifne          67
      63: iconst_1
      64: goto          68
      67: iconst_0
      68: invokestatic  #78                 // Method kotlin/coroutines/jvm/internal/Boxing.boxBoolean:(Z)Ljava/lang/Boolean;
      71: invokestatic  #84                 // Method kotlin/jvm/internal/Intrinsics.stringPlus:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
      74: invokestatic  #89                 // Method android/util/Log.i:(Ljava/lang/String;Ljava/lang/String;)I
      77: pop
      78: ldc           #51                 // String MainActivity
      80: ldc           #91                 // String launchWhenResumed,threadId:
      82: invokestatic  #59                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
      85: invokevirtual #63                 // Method java/lang/Thread.getId:()J
      88: invokestatic  #95                 // Method kotlin/coroutines/jvm/internal/Boxing.boxLong:(J)Ljava/lang/Long;
      91: invokestatic  #84                 // Method kotlin/jvm/internal/Intrinsics.stringPlus:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
      94: invokestatic  #89                 // Method android/util/Log.i:(Ljava/lang/String;Ljava/lang/String;)I
      97: pop
      98: invokestatic  #101                // Method kotlinx/coroutines/Dispatchers.getMain:()Lkotlinx/coroutines/MainCoroutineDispatcher;
     101: checkcast     #103                // class kotlin/coroutines/CoroutineContext
     104: new           #105                // class com/devnn/demo/MainActivity$onCreate$6$1
     107: dup
     108: aconst_null
     109: invokespecial #107                // Method com/devnn/demo/MainActivity$onCreate$6$1."<init>":(Lkotlin/coroutines/Continuation;)V
     112: checkcast     #7                  // class kotlin/jvm/functions/Function2
     115: aload_0
     116: checkcast     #109                // class kotlin/coroutines/Continuation
     119: aload_0
     120: iconst_1
     121: putfield      #43                 // Field label:I
     124: invokestatic  #115                // Method kotlinx/coroutines/BuildersKt.withContext:(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
     127: dup
     128: aload_2
     129: if_acmpne     139
     132: aload_2
     133: areturn
     134: aload_1
     135: invokestatic  #49                 // Method kotlin/ResultKt.throwOnFailure:(Ljava/lang/Object;)V
     138: aload_1
     139: pop
     140: invokestatic  #119                // Method kotlinx/coroutines/Dispatchers.getIO:()Lkotlinx/coroutines/CoroutineDispatcher;
     143: checkcast     #103                // class kotlin/coroutines/CoroutineContext
     146: new           #121                // class com/devnn/demo/MainActivity$onCreate$6$2
     149: dup
     150: aconst_null
     151: invokespecial #122                // Method com/devnn/demo/MainActivity$onCreate$6$2."<init>":(Lkotlin/coroutines/Continuation;)V
     154: checkcast     #7                  // class kotlin/jvm/functions/Function2
     157: aload_0
     158: checkcast     #109                // class kotlin/coroutines/Continuation
     161: aload_0
     162: iconst_2
     163: putfield      #43                 // Field label:I
     166: invokestatic  #115                // Method kotlinx/coroutines/BuildersKt.withContext:(Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
     169: dup
     170: aload_2
     171: if_acmpne     181
     174: aload_2
     175: areturn
     176: aload_1
     177: invokestatic  #49                 // Method kotlin/ResultKt.throwOnFailure:(Ljava/lang/Object;)V
     180: aload_1
     181: pop
     182: getstatic     #128                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
     185: areturn
     186: new           #130                // class java/lang/IllegalStateException
     189: dup
     190: ldc           #132                // String call to 'resume' before 'invoke' with coroutine
     192: invokespecial #135                // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
     195: athrow

  public final kotlin.coroutines.Continuation<kotlin.Unit> create(java.lang.Object, kotlin.coroutines.Continuation<?>);
    Code:
       0: new           #2                  // class com/devnn/demo/MainActivity$onCreate$6
       3: dup
       4: aload_2
       5: invokespecial #145                // Method "<init>":(Lkotlin/coroutines/Continuation;)V
       8: checkcast     #109                // class kotlin/coroutines/Continuation
      11: areturn

  public final java.lang.Object invoke(kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<? super kotlin.Unit>);
    Code:
       0: aload_0
       1: aload_1
       2: aload_2
       3: invokevirtual #151                // Method create:(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
       6: checkcast     #2                  // class com/devnn/demo/MainActivity$onCreate$6
       9: getstatic     #128                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
      12: invokevirtual #153                // Method invokeSuspend:(Ljava/lang/Object;)Ljava/lang/Object;
      15: areturn

  public java.lang.Object invoke(java.lang.Object, java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #159                // class kotlinx/coroutines/CoroutineScope
       5: aload_2
       6: checkcast     #109                // class kotlin/coroutines/Continuation
       9: invokevirtual #161                // Method invoke:(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
      12: areturn
}

这个匿名内部类只有一个字段就是int类型的label。同时它的主要业务逻辑代码在invokeSuspend函数中,这个函数里面有一个tableswitch的判断,根据label的值,判断跳转到哪一块代码执行。看这个有点类似有限状态机。

Function2接口内容:

public interface Function2<in P1, in P2, out R> : Function<R> {
   /** Invokes the function with the specified arguments. */
  public operator fun invoke(p1: P1, p2: P2): R
}

MainActivity的协程中有两段withContext{}代码块,它们也被封装成了匿名内部类,这个匿名内部类跟外部的协程代码块一样,继承了SuspendLambda类,同时实现了Function2接口。

第一个withContext代码块的匿名内部类是com/devnn/demo/MainActivity\$onCreate\$6\$1.class

第二个withContext代码块的匿名内部类是com/devnn/demo/MainActivity\$onCreate\$6\$2.class

转载请注明来源:
https://blog.csdn.net/devnn/article/details/135610313

com/devnn/demo/MainActivity\$onCreate\$6\$1.class的内容如下:

final class com.devnn.demo.MainActivity$onCreate$6$1 extends kotlin.coroutines.jvm.internal.SuspendLambda implements kotlin.jvm.functions.Function2<kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<? super java.lang.Integer>, java.lang.Object> {
  int label;

  com.devnn.demo.MainActivity$onCreate$6$1(kotlin.coroutines.Continuation<? super com.devnn.demo.MainActivity$onCreate$6$1>);
    Code:
       0: aload_0
       1: iconst_2
       2: aload_1
       3: invokespecial #13                 // Method kotlin/coroutines/jvm/internal/SuspendLambda."<init>":(ILkotlin/coroutines/Continuation;)V
       6: return

  public final java.lang.Object invokeSuspend(java.lang.Object);
    Code:
       0: invokestatic  #37                 // Method kotlin/coroutines/intrinsics/IntrinsicsKt.getCOROUTINE_SUSPENDED:()Ljava/lang/Object;
       3: pop
       4: aload_0
       5: getfield      #41                 // Field label:I
       8: tableswitch   { // 0 to 0
                     0: 28
               default: 61
          }
      28: aload_1
      29: invokestatic  #47                 // Method kotlin/ResultKt.throwOnFailure:(Ljava/lang/Object;)V
      32: ldc2_w        #48                 // long 10000l
      35: invokestatic  #55                 // Method java/lang/Thread.sleep:(J)V
      38: ldc           #57                 // String MainActivity
      40: ldc           #59                 // String launchWhenResumed,withContext1,threadId:
      42: invokestatic  #63                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
      45: invokevirtual #67                 // Method java/lang/Thread.getId:()J
      48: invokestatic  #73                 // Method kotlin/coroutines/jvm/internal/Boxing.boxLong:(J)Ljava/lang/Long;
      51: invokestatic  #79                 // Method kotlin/jvm/internal/Intrinsics.stringPlus:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
      54: invokestatic  #84                 // Method android/util/Log.i:(Ljava/lang/String;Ljava/lang/String;)I
      57: invokestatic  #88                 // Method kotlin/coroutines/jvm/internal/Boxing.boxInt:(I)Ljava/lang/Integer;
      60: areturn
      61: new           #90                 // class java/lang/IllegalStateException
      64: dup
      65: ldc           #92                 // String call to 'resume' before 'invoke' with coroutine
      67: invokespecial #95                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      70: athrow

  public final kotlin.coroutines.Continuation<kotlin.Unit> create(java.lang.Object, kotlin.coroutines.Continuation<?>);
    Code:
       0: new           #2                  // class com/devnn/demo/MainActivity$onCreate$6$1
       3: dup
       4: aload_2
       5: invokespecial #102                // Method "<init>":(Lkotlin/coroutines/Continuation;)V
       8: checkcast     #104                // class kotlin/coroutines/Continuation
      11: areturn

  public final java.lang.Object invoke(kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<? super java.lang.Integer>);
    Code:
       0: aload_0
       1: aload_1
       2: aload_2
       3: invokevirtual #110                // Method create:(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
       6: checkcast     #2                  // class com/devnn/demo/MainActivity$onCreate$6$1
       9: getstatic     #116                // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
      12: invokevirtual #118                // Method invokeSuspend:(Ljava/lang/Object;)Ljava/lang/Object;
      15: areturn

  public java.lang.Object invoke(java.lang.Object, java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #124                // class kotlinx/coroutines/CoroutineScope
       5: aload_2
       6: checkcast     #104                // class kotlin/coroutines/Continuation
       9: invokevirtual #126                // Method invoke:(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
      12: areturn
}

com.devnn.demo.MainActivity$onCreate$6$2的内容如下:

final class com.devnn.demo.MainActivity$onCreate$6$2 extends kotlin.coroutines.jvm.internal.SuspendLambda implements kotlin.jvm.functions.Function2<kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<? super kotlin.Unit>, java.lang.Object> {
  int label;

  com.devnn.demo.MainActivity$onCreate$6$2(kotlin.coroutines.Continuation<? super com.devnn.demo.MainActivity$onCreate$6$2>);
    Code:
       0: aload_0
       1: iconst_2
       2: aload_1
       3: invokespecial #13                 // Method kotlin/coroutines/jvm/internal/SuspendLambda."<init>":(ILkotlin/coroutines/Continuation;)V
       6: return

  public final java.lang.Object invokeSuspend(java.lang.Object);
    Code:
       0: invokestatic  #37                 // Method kotlin/coroutines/intrinsics/IntrinsicsKt.getCOROUTINE_SUSPENDED:()Ljava/lang/Object;
       3: pop
       4: aload_0
       5: getfield      #41                 // Field label:I
       8: tableswitch   { // 0 to 0
                     0: 28
               default: 56
          }
      28: aload_1
      29: invokestatic  #47                 // Method kotlin/ResultKt.throwOnFailure:(Ljava/lang/Object;)V
      32: ldc           #49                 // String MainActivity
      34: ldc           #51                 // String launchWhenResumed,withContext2,threadId:
      36: invokestatic  #57                 // Method java/lang/Thread.currentThread:()Ljava/lang/Thread;
      39: invokevirtual #61                 // Method java/lang/Thread.getId:()J
      42: invokestatic  #67                 // Method kotlin/coroutines/jvm/internal/Boxing.boxLong:(J)Ljava/lang/Long;
      45: invokestatic  #73                 // Method kotlin/jvm/internal/Intrinsics.stringPlus:(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;
      48: invokestatic  #78                 // Method android/util/Log.i:(Ljava/lang/String;Ljava/lang/String;)I
      51: pop
      52: getstatic     #84                 // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
      55: areturn
      56: new           #86                 // class java/lang/IllegalStateException
      59: dup
      60: ldc           #88                 // String call to 'resume' before 'invoke' with coroutine
      62: invokespecial #91                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      65: athrow

  public final kotlin.coroutines.Continuation<kotlin.Unit> create(java.lang.Object, kotlin.coroutines.Continuation<?>);
    Code:
       0: new           #2                  // class com/devnn/demo/MainActivity$onCreate$6$2
       3: dup
       4: aload_2
       5: invokespecial #98                 // Method "<init>":(Lkotlin/coroutines/Continuation;)V
       8: checkcast     #100                // class kotlin/coroutines/Continuation
      11: areturn

  public final java.lang.Object invoke(kotlinx.coroutines.CoroutineScope, kotlin.coroutines.Continuation<? super kotlin.Unit>);
    Code:
       0: aload_0
       1: aload_1
       2: aload_2
       3: invokevirtual #106                // Method create:(Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Lkotlin/coroutines/Continuation;
       6: checkcast     #2                  // class com/devnn/demo/MainActivity$onCreate$6$2
       9: getstatic     #84                 // Field kotlin/Unit.INSTANCE:Lkotlin/Unit;
      12: invokevirtual #108                // Method invokeSuspend:(Ljava/lang/Object;)Ljava/lang/Object;
      15: areturn

  public java.lang.Object invoke(java.lang.Object, java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #114                // class kotlinx/coroutines/CoroutineScope
       5: aload_2
       6: checkcast     #100                // class kotlin/coroutines/Continuation
       9: invokevirtual #116                // Method invoke:(Lkotlinx/coroutines/CoroutineScope;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
      12: areturn
}

每次执行新的匿名内部类代码(就是withContext代码块)时,就把当前这个匿名内部类传递给了新的匿名内部类。注意每个匿名内部类都是Continuation的实现。看到这里就知道其实Continuation就是一个回调。这其实就跟Java的回调一样,只是Kotlin隐式地实现了回调,并且加了状态机机制。每次执行一段suspend代码之后,将状态值修改成新值,执行回调时就知道走哪一段代码块。

转载请注明来源:
https://blog.csdn.net/devnn/article/details/135610313

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/324543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML--CSS--浮动布局及定位布局

正常文档布局 块元素独占一行 行内元素在有多个的时候&#xff0c;就是从左到右排在一行 块元素包括&#xff1a;div,p,hr 行内元素&#xff1a;span,i,img 浮动布局 float 属性&#xff1a; left 向左 right 向右 作用我目前看起来就是浮动元素的宽度是由内容决定的&#x…

MySQL面试题 | 10.精选MySQL面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

LLM之幻觉(二):大语言模型LLM幻觉缓减技术综述

LLM幻觉缓减技术分为两大主流&#xff0c;梯度方法和非梯度方法。梯度方法是指对基本LLM进行微调&#xff1b;而非梯度方法主要是在推理时使用Prompt工程技术。LLM幻觉缓减技术&#xff0c;如下图所示&#xff1a; LLM幻觉缓减技术值得注意的是&#xff1a; 检索增强生成&…

pytorch集智-5手写数字识别器-卷积神经网络

1 简介 简称&#xff1a;CNN&#xff0c;convolutional neural network 应用场景&#xff1a;图像识别与分类&#xff08;CNN&#xff09;&#xff0c;看图说话&#xff08;CNNRNN&#xff09;等 优越性&#xff1a;和多层感知机相比&#xff0c;cnn可以识别独特的模式&…

如何做用户分层和标签体系

“活动作了一场接一场&#xff0c;简直要累死了&#xff0c;拉进来的客户也没有多少&#xff0c;投入产出完全不成比例&#xff0c;怎么办&#xff1f;“ “有那么多注册用户&#xff0c;但是GMV怎么才这么点&#xff0c;他们怎么不买啊&#xff0c;难道都是羊毛党&#xff1f;…

使用 TiUP 部署 TiDB 集群

TIDB优点 支持分布式且支持事务的关系型数据库&#xff0c;不用考虑分库分表 同时满足了可伸缩&#xff0c;高可用&#xff0c;关系型&#xff0c;支持事务。 基本上按官网的文档来就行了。 在线部署 以普通用户身份登录中控机。以 tidb 用户为例&#xff0c;后续安装 TiUP …

常用界面设计组件 —— 窗体(QT)

二、常用界面设计组件2.1 窗体2.1.1 设置窗体位置、大小及背景颜色2.1.2 设置窗体标题2.1.3 多窗体调用 二、常用界面设计组件 组件是GUI的基本元素&#xff0c;也称为UI控件。它接受来自底层平台的不同用户事件&#xff0c;如鼠标和键盘事件&#xff08;以及其它事件&#xf…

漏洞复现-Yearning front 任意文件读取漏洞(附漏洞检测脚本)

免责声明 文章中涉及的漏洞均已修复&#xff0c;敏感信息均已做打码处理&#xff0c;文章仅做经验分享用途&#xff0c;切勿当真&#xff0c;未授权的攻击属于非法行为&#xff01;文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的…

7_1 tesseract 安装及使用

1、 安装tesseract   OCR&#xff0c;即Optical Character Recognition&#xff0c;光学字符识别&#xff0c;是指通过扫描字符&#xff0c;然后通过其形状将其翻译成电子文本的过程。对于图形验证码来说&#xff0c;它们都是一些不规则的字符&#xff0c;这些字符确实是由字…

助力工业焊缝质量检测,YOLOv7【tiny/l/x】不同系列参数模型开发构建工业焊接场景下钢材管道焊缝质量检测识别分析系统

焊接是一个不陌生但是对于开发来说相对小众的场景&#xff0c;在我们前面的博文开发实践中也有一些相关的实践&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a;《轻量级模型YOLOv5-Lite基于自己的数据集【焊接质量检测】从零构建模型超详细教程》 《基于DeepLabV3Plus…

Android 仿快手视频列表,RecyclerView与Banner联动效果

这是看到群里讨论过快手APP的一个观看他人视频列表的一个联动效果&#xff0c;但是并不是完全按照这个软件的效果来做的&#xff0c;只是参考&#xff0c;并不是完全仿照这个软件来做的&#xff0c;没时间去优化排版问题了&#xff0c;请见谅&#xff0c;如图&#xff1a; 实现…

[链路层] 点对点协议 PPP

目录 1、PPP协议的特点 2、PPP协议的组成和帧格式 3、PPP协议的工作状态 目前使用得最广泛的数据链路层协议是点对点协议PPP(Point-to-Point Protocol)。 1、PPP协议的特点 我们知道&#xff0c;互联网用户通常都要连接到某个 ISP 才能接入到互联网。PPP 协议就是用户计算机…

【物以类聚】给el-image预览多张图片增加提示文字,让每张图片有所分类

【物以类聚】给el-image预览多张图片增加提示文字&#xff0c;让每张图片有所分类 一、需求二、el-image三、实施步骤3.1 导包3.2 改造3.3 引入 三、效果 一、需求 点击地图上的一张图片&#xff0c;弹出所有相关的图片资源&#xff0c;图片资源上显示每个图片的所属类型。 二…

一文读懂「Large Language Model,LLM」大语言模型

中国大语言模型产业价值链 资料 艾瑞咨询&#xff1a;https://www.iresearch.com.cn/Detail/report?id4166&isfree0&type

五指CMS copyfrom.php SQL注入漏洞复现(CVE-2023-52064)

0x01 产品简介 WUZHI CMS是北京五指互联科技有限公司 的一套基于PHP和MySQL的开源内容管理系统,响应式布局,一个网站兼容多个终端 微信接口全支持,快速构建微营销平台 开放接口,支持第三方APP无缝接入。 0x02 漏洞概述 Wuzhicms 内容管理系统的/core/admin/copyfrom.p…

vue基于spring boot框架的发艺美发店理发店管理系统的设计q9xpe

店铺信息、美发信息是发艺美发店管理系统的重要组成部分&#xff0c;信息清晰、详细、准确&#xff0c;能够有效地促进发艺美发店管理系统的运行[5]。基础设定函数是对整个系统的总体布局进行合理安排&#xff0c;包括&#xff1a;店铺活动、物品信息、领用信息等。通过对各类资…

openpyxl绘制图表

嘿&#xff0c;你是不是在处理Excel文件时感到束手无策&#xff1f;是不是想要一个简单而又强大的工具来处理数据分析和图表制作&#xff1f;别担心&#xff0c;我们有解决方案&#xff01;让我向你介绍openpyxl&#xff0c;这是一个Python库&#xff0c;专门用于处理Excel文件…

通过myBatis将sql语句返回的值自动包装成一个java对象(2)

1.之前我们是如何执行一个sql语句自动包装成一个java对象呢&#xff1f; 1.创建一个mapper.xml&#xff0c;定义 执行的语句名字 和 包装成什么类 2.在总的配置文件里申明这个mapper 3.在java里通过sqlSession执行mapper里定义好的内容 我们还可以使用另一种方法实现第三步。现…

力扣每日一练(24-1-16)

我一开始想到的是&#xff0c;如果数字相同则加一。 然而&#xff0c;对了一点点&#xff0c;而已。 高手的方法不是普通人在几分钟内能想得出来的&#xff0c;hh 继续补充&#xff1a; 如果数字不同则减一&#xff0c;如果计数到达了0&#xff0c;则更新数字&#xff0c;最…

AWS边缘媒体安全交付方案

企业如何在AWS上的边缘站点&#xff0c;安全的将优质视频内容交付给用户&#xff0c;并且禁止哪些未经过授权的访问&#xff1f;九河云将基于AWS平台提供边缘媒体安全交付解决方案 解决方案详情 在通过 Amazon CloudFront 交付时&#xff0c;免受未经授权的访问。基于添加到交…