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


文章插图

  • 从下图可见,那个临时变量runOnVirtualThread其实来自方法isRunOnVirtualThread

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

文章插图
  • 打开EndpointIndexer#isRunOnVirtualThread方法,如下图,如果某个类的某个方法被添加了@RunOnVirtualThread注解,那么下面的getInheritableAnnotation方法返回的就是从此方法中取得的注解对象

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

文章插图
  • 至于上图中的getInheritableAnnotation方法,我觉得很有必要看一眼,就一眼...,如下图,可见,@RunOnVirtualThread注解不论是写在方法上还是类上都有效

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

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

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

文章插图
  • 现在,重点来了!!!
  • 上图红色箭头的代码在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如何支持虚拟线程

文章插图