支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程( 二 )

支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程
文章插图

  • 至此,可以小结了:咱们开发web服务的过程中,为web服务类添加的@RunOnVirtualThread , 都存入了ResourceMethod对象中
  • 上面这个结论很重要,后面会用到
  • 现在已经顺利弄明白了第一个问题:@RunOnVirtualThread注解去哪了?继续下一个:那个特别的Executor对象是怎么诞生的?
关于Executor
  • 本篇最重要的内容就是一个特别的Executor对象,现在就来聚焦它 , 先看它的创建过程
  • quarkus应用启动的时候,方法ResteasyReactiveProcessor#setupDeployment会执行 , 主要是完成应用启动是的一些初始化操作,里面代码很多 , 下图箭头所指是本篇最关心的,里面会提取bean的注解做对应的处理

支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程

文章插图
  • 现在,重点来了?。。?/li>
  • 上图红色箭头的代码在ResteasyReactiveRecorder.java中,来看这个createDeployment方法 , 如下图,第一个箭头处 , 出现了一个静态变量,名为VIRTUAL_EXECUTOR_SUPPLIER,它先被传给了RuntimeDeploymentManager对象,然后在箭头2位置,RuntimeDeploymentManager对象的deploy中,就会用到这个VIRTUAL_EXECUTOR_SUPPLIER

支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程

文章插图
  • 接下来兵分两路,先看上图箭头1中的VIRTUAL_EXECUTOR_SUPPLIER是什么 , 再看箭头2的deploy中如何使用VIRTUAL_EXECUTOR_SUPPLIER
首先,VIRTUAL_EXECUTOR_SUPPLIER是什么
  • 在看之前,先回顾一下JDK官方指导是如何使用虚拟线程的,如下图 , 一共两步:先调用Executors.newVirtualThreadPerTaskExecutor()创建一个Executor实例(没错,就是咱们平时写多线程代码时的那个Executor),再执行executor.submit方法,这样就创建了虚拟线程,并在虚拟线程中执行业务逻辑:

支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程

文章插图
  • 现在去看创建VIRTUAL_EXECUTOR_SUPPLIER的代码就会特别清晰了,如下图,前面在JDK官方指导看到的Executors.newVirtualThreadPerTaskExecutor(),在quarkus这里被改为用反射实现 , 这样可以避免JDK19以下的环境中出现编译问题,箭头3位置的代码也很重要,如果当前环境不支持虚拟线程,就会返回一个可用的executor,确保业务能执行下去

支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程

文章插图
  • 对于上图箭头3位置的做法,个人并不认同:我使用虚拟线程,就是想一口气创建成千上万线程 , 再肆无忌惮的使用,遇到不支持虚拟线程的场景,直接抛异常让我知道这条路走不通,逼我再去想办法解决,这样不好么?而箭头3位置显然返回的是传统线程,这么一来 , 岂不是成了创建成千上万的传统线程了?这谁扛得?。抗丶? ,在开发阶段,因为条件所限 , 可能只构造了少量线程来验证基本功能,如果就这样发布到生产环境,就有可能创建大量传统线程,导致CPU的内核态使用率上涨,影响系统整体性能
  • 至此,咱们算是搞清楚这个executor是啥了:用Executors.newVirtualThreadPerTaskExecutor()创建的Executor实例,虽然是用反射,但本质上得到的结果和JDK方法的推荐做法一致
其次 , RuntimeDeploymentManager#deploy方法里是什么?
  • 刚才说好的兵分两路,先看VIRTUAL_EXECUTOR_SUPPLIER是什么,再看RuntimeDeploymentManager#deploy()方法
  • 该方法内容很多 , 咱们还是只看虚拟线程有关的,如下图,VIRTUAL_EXECUTOR_SUPPLIER成了runtimeResourceDeployment的成员变量 , 然后针对每个bean的每个方法 , 都要执行一次箭头4指向的buildResourceMethod方法,此方法是关键,接下来重点看

支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程

文章插图
  • 展开上图箭头4的方法,原来如此,注意箭头指向的method.isRunOnVirtualThread() , 这个在前面已经分析过了,咱们用@isRunOnVirtualThread修饰过的web接口,在这里返回的值就是true,就会执行箭头2所指的代码,为此web接口添加一个handler , 从名字上看,这个blockingHandlerVirtualThread和之前咱们一直关注的VIRTUAL_EXECUTOR_SUPPLIER应该有不小的关系

支持JDK19虚拟线程的web框架之四:看源码,了解quarkus如何支持虚拟线程

文章插图