前提国庆前后,我看了虚拟线程相关的源码,写了一篇《虚拟线程- VirtualThread源码透视》,里面介绍了虚拟线程的实现原理和使用实例。你需要做一些初步的准备:
安装OpenJDK-19或Oracle JDK-19,准备嵌入式Tomcat的依赖,需要引入三个依赖包,分别是tomcat-embed-core、tomcat-embed-el和tomcat-embed-websocket。版本是10.1.小编查看Tomcat官方文档的CHANGELOG:
支持Loom项目的Tomcat最低版本是10.1.0-M16,对应的正式版本是10.1.0(目前时间是2022-10-07左右),低于这个版本是因为大量API还没有适配虚拟线程,主要是因为没有修改监控锁的引用,导致虚拟线程pin到载体(平台)线程等问题,所以没有其他选择。另外,重要提醒说三遍:
本文是实验性的,在完全确认转换函数可以应用于生产环境之前需要仔细评估,或者在完全确认转换函数可以应用于生产环境之前需要仔细评估,或者在完全确认转换函数可以应用于生产环境之前需要仔细评估。
相关性介绍相关性介绍以下相关性:
& lt依赖性& gt& ltgroupId & gtorg . Apache . Tomcat . embed & lt;/groupId & gt;& ltartifactId & gtTomcat -embed -core & lt;/artifact id & gt;& lt版本& gt10 . 1 . 0 & lt;/version & gt;& lt/dependency & gt;& lt依赖性& gt& ltgroupId & gtorg . Apache . Tomcat . embed & lt;/groupId & gt;& ltartifactId & gtTomcat -embed -El & lt;/artifact id & gt;& lt版本& gt10 . 1 . 0 & lt;/version & gt;& lt/dependency & gt;& lt依赖性& gt& ltgroupId & gtorg . Apache . Tomcat . embed & lt;/groupId & gt;& ltartifactId & gtTomcat -embed -web socket & lt;/artifact id & gt;& lt版本& gt10 . 1 . 0 & lt;/version & gt;& lt/dependency & gt;
程序化初始化Tomcat为了使用反射调用java.base模块下一些未打开的依赖包,跟踪虚拟线程栈,在程序运行过程中增加了以下VM参数:
--add -开启java.base/java.lang=ALL-UNNAMED --add -开启java.base/java.lang.reflect=ALL-UNNAMED --add -开启java.base/ Java . util . concurrent = all -未命名-djdk . tracepinedthreads = full在IDEA的运行配置中是这样的:
然后编写一个HttpServlet实现:
公共类VirtualThreadHandleServlet扩展http servlet { private static final datetime FORMATTER FORMATTER = datetime FORMATTER . of pattern(" yyyy -MM-DD HH:mm:ss。SSS”);@ Override protected void service(http servlet request req,HttpServletResponse resp)抛出ServletException,io exception { Thread Thread = Thread . current Thread();system . out . printf(" service by thread = = & gt;%s是虚拟的= = & gt%s,载体线程= = & gt%s\n ",thread.getName(),thread.isVirtual(),getCurrentCarrierThreadName(thread));resp . set status(http servlet response。SC _ OK);resp.setHeader("Content-Type "," application/JSON ");string content = " { \ " time \ ":"+" \ "+local datetime . now()。format(格式化程序)+" \ " } ";resp.getWriter()。写(内容);}私有静态字符串getCurrentCarrierThreadName(Thread current Thread){ if(current Thread . is virtual()){ try { method handle method handle = method handles . privatelookupin(Thread . class,MethodHandles.lookup())。findStatic(Thread.class," currentCarrierThread ",method type . method type(thread . class));Thread carrier Thread =(Thread)method handle . invoke();返回carrier thread . getname();} catch(Throwable e){ e . printstacktrace();} }返回“未知”;} } Servlet的实现比较简单,就是在控制台上打印一些虚拟线程和载体线程的信息,然后返回HTTP状态码200和一个JSON字符来显示当前精确到毫秒的时间。然后编写一个main方法来初始化Tomcat:
public类EmbedTomcatVirtualThreadDemo { private static final String SERVLET _ NAME = " VirtualThreadHandleServlet ";私有静态最终字符串SERVLET _ PATH = "/* ";/* * *设置VM参数:* --add -打开java.base/java.lang=ALL-UNNAMED * --add -打开java.base/java.lang.reflect=ALL-UNNAMED * --add -打开java.base/java.util.concurrent=ALL-UNNAMED * -djdk . tracepinnedthreads = full * * @ param args args * @抛出异常e */ public static void main(String
这里确认了Tomcat在127.0.0.1:9091开始并结束监听,通过浏览器或POSTMAN发送任何请求如http://127.0.0.1:9091/foo都可以看到响应结果和控制台输出:
这里的Tomcat线程池甚至可以被设计成一个完全定制的虚拟线程调度器。可以参考之前的文章,这里就不赘述了。
暂时不能用于跳靴系统。由于Servlet规范问题,Tomcat的升级导致了部分接口迁移到jakarta.servlet包,比如这次的jakarta.servlet.Servlet,即使SpringBoot系统是最新版本(当前时间是2022-10-07左右,此时最新版本是2.7.4)。它仍然使用旧的规范,它对应的类是javax。Servlet.Servlet,这只是其中一个接口。大部分与HTTP协议或servlet规范相关的接口都存在包升级不兼容的问题,需要等待SpringBoot升级到embed-tomcat-*-10.1.小编才能适应虚拟线程。
摘要演示项目仓库:
github:https://github . com/ZJ cscut/framework -mesh/tree/master/Tomcat -virtual -thread
这就是本文关于在Tomcat中启用虚拟线程的内容。关于在Tomcat中启用虚拟线程的更多信息,请搜索主机频道zhujipindao以前的文章。或者继续浏览下面的相关文章。希望大家支持主机频道zhujipindao。以后多来com!
评论前必须登录!
注册