前提趁着国庆前后阅读了虚拟线程相关的源码,写了一篇《虚拟线程 - VirtualThread源码透视》,里面介绍了虚拟线程的实现原理和使用示例 。需要准备做一下前期准备:
- 安装OpenJDK-19或者Oracle JDK-19
- 准备好嵌入式Tomcat的依赖,需要引入三个依赖包,分别是tomcat-embed-core、tomcat-embed-el和tomcat-embed-websocket,版本选用10.1.0+
文章插图
支持Loom项目的Tomcat最低版本为10.1.0-M16,对应的正式版是10.1.0(当前时间为2022-10-07前后),低于此版本因为大量API还没有适配虚拟线程,主要是没有改造监视器锁的引用导致虚拟线程pin到载体(平台)线程等问题,因此别无他选 。另外,重要的提醒说三次:
- 本文是实验性质 , 在未完全证实改造功能可以应用生产环境前需要谨慎评估,或者先别使用于生产环境
- 本文是实验性质 , 在未完全证实改造功能可以应用生产环境前需要谨慎评估 , 或者先别使用于生产环境
- 本文是实验性质,在未完全证实改造功能可以应用生产环境前需要谨慎评估,或者先别使用于生产环境
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>10.1.0</version></dependency><dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-el</artifactId> <version>10.1.0</version></dependency><dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-websocket</artifactId> <version>10.1.0</version></dependency>编程式初始化Tomcat为了使用反射调用一些java.base模块下没开放的依赖包和跟踪虚拟线程栈 , 程序运行时候加入下面的VM参数:
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED -Djdk.tracePinnedThreads=full在IDEA的运行配置中是这个样子:
文章插图
接着编写一个HttpServlet实现:
public class VirtualThreadHandleServlet extends HttpServlet { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Thread thread = Thread.currentThread(); System.out.printf("service by thread ==> %s, is virtual ==> %s, carrier thread ==> %s\n", thread.getName(), thread.isVirtual(), getCurrentCarrierThreadName(thread)); resp.setStatus(HttpServletResponse.SC_OK); resp.setHeader("Content-Type", "application/json"); String content = "{\"time\":" + "\"" + LocalDateTime.now().format(FORMATTER) + "\"}"; resp.getWriter().write(content); } private static String getCurrentCarrierThreadName(Thread currentThread) { if (currentThread.isVirtual()) { try { MethodHandle methodHandle = MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup()) .findStatic(Thread.class, "currentCarrierThread", MethodType.methodType(Thread.class)); Thread carrierThread = (Thread) methodHandle.invoke(); return carrierThread.getName(); } catch (Throwable e) { e.printStackTrace(); } } return "UNKNOWN"; }}
推荐阅读
- Java19虚拟线程都来了,我正在写的线程代码会被淘汰掉吗?
- 光遇欧若拉季神龛位置在哪
- 东北往事之黑道风云20年第二部全集电视剧在线观看 东北黑道风云二十年
- realmev15耳机插孔在哪里_realmev15耳机孔
- 文件截图怎么截图(怎么在文件里随便截图)
- 怎么如何截图(如何在微信上截图发送)
- 在PE文件中简单注入代码,实现在启动前弹窗
- 邮政投诉-中国邮政投诉网站
- 从 C# 崩溃异常 中研究页堆布局
- .Net WebApi 中的 FromBody FromForm FromQuery FromHeader FromRoute