该Servlet实现比较简单,就是在控制台打印一些虚拟线程和载体线程的一些信息,然后返回HTTP状态码为200和一个JSON字符展示当前精确到毫秒的时间 。接着编写一个main方法初始化Tomcat:
public class EmbedTomcatVirtualThreadDemo { private static final String SERVLET_NAME = "VirtualThreadHandleServlet"; private static final String SERVLET_PATH = "/*"; /** * 设置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 * * @param args args * @throws Exception e */ public static void main(String[] args) throws Throwable { String pinMode = System.getProperty("jdk.tracePinnedThreads"); System.out.println("pin mode = " + pinMode); Tomcat tomcat = new Tomcat(); Context context = tomcat.addContext("", (new File(".")).getAbsolutePath()); Tomcat.addServlet(context, SERVLET_NAME, new VirtualThreadHandleServlet()); context.addServletMappingDecoded(SERVLET_PATH, SERVLET_NAME); Connector connector = new Connector(); ProtocolHandler protocolHandler = connector.getProtocolHandler(); if (protocolHandler instanceof AbstractProtocol<?> protocol) { protocol.setAddress(InetAddress.getByName("127.0.0.1")); protocol.setPort(9091); ThreadFactory factory = Thread.ofVirtual().name("embed-tomcat-virtualWorker-", 0).factory(); Class<?> klass = Class.forName("java.util.concurrent.ThreadPerTaskExecutor"); MethodHandle methodHandle = MethodHandles.privateLookupIn(klass, MethodHandles.lookup()) .findStatic(klass, "create", MethodType.methodType(klass, new Class[]{ThreadFactory.class})); ExecutorService executor = (ExecutorService) methodHandle.invoke(factory); protocol.setExecutor(executor); } tomcat.getService().addConnector(connector); tomcat.start(); }}这里VirtualThreadHandleServlet匹配所有格式的请求路径并且处理所有请求方法类型的请求 。默认的虚拟线程调度器没有为虚拟线程设置名称,也就是如果使用Executors.newVirtualThreadPerTaskExecutor()作为Tomcat的线程池是最终调用看到的控制台输出的虚拟线程名称是一个空字符串 。所以笔者这里用MethodHandle直接实例化了默认修饰符没有开放访问权限的ThreadPerTaskExecutor类,基于一个自定义的ThreadFactory强制构造了一个自定义ThreadPerTaskExecutor实例 。调用main方法启动后见控制台输出:
【在Tomcat中启用虚拟线程特性】
文章插图
这里确认了Tomcat启动完成侦听127.0.0.1:9091,通过浏览器或者POSTMAN发送任意请求例如http://127.0.0.1:9091/foo就能看到响应结果和控制台输出:
文章插图
这里的Tomcat线程池甚至可以设计为一个完全自定义的虚拟线程调度器,可以参考前面一篇文章,这里不再赘述 。
推荐阅读
- Java19虚拟线程都来了,我正在写的线程代码会被淘汰掉吗?
- 光遇欧若拉季神龛位置在哪
- 东北往事之黑道风云20年第二部全集电视剧在线观看 东北黑道风云二十年
- realmev15耳机插孔在哪里_realmev15耳机孔
- 文件截图怎么截图(怎么在文件里随便截图)
- 怎么如何截图(如何在微信上截图发送)
- 在PE文件中简单注入代码,实现在启动前弹窗
- 邮政投诉-中国邮政投诉网站
- 从 C# 崩溃异常 中研究页堆布局
- .Net WebApi 中的 FromBody FromForm FromQuery FromHeader FromRoute