You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让虚拟线程让出执行权?解决MySQL驱动与虚拟线程兼容问题

问题背景
  • 发现mysql-connect-java与虚拟线程不兼容,开启-Djdk.tracePinnedThreads=full后出现固定栈轨迹。
  • 问题:如何解决该兼容问题?已尝试将synchronized替换为ReentrantLock,但无效。
  • 考虑另一种方案:让虚拟线程让出执行权到平台线程。
  • 测试环境:SpringMVC开启虚拟线程(spring.threads.virtual.enabled = true),虚拟线程创建方式为Thread.ofVirtual().name("testvt").start(task),参考Tomcat相关实现。
我的尝试
public static ThreadPoolExecutor bizPoolExecutor = new ThreadPoolExecutor(
        4,
        60,
        60,
        TimeUnit.SECONDS,
        new LinkedBlockingDeque<>(10000),
        new TaskThreadFactory("mysqlExecPool-"),
        new ThreadPoolExecutor.CallerRunsPolicy());

public CompletableFuture<List<ResultData>> getDataAsync() {
    CompletableFuture<List<ResultData>> finalRet = CompletableFuture.supplyAsync(() -> {
        List<ResultData> result = getData();
        return result;
    }, bizPoolExecutor);
    return finalRet;
}

public List<ResultData> getData() {
    long begin = System.currentTimeMillis();
    String sql = "select * from user where uid=1234";
    List<ResultData> resultDataList = wjt.query(sql, identifyLogRowMapper);
    long end = System.currentTimeMillis();
    log.info("mysql cost:{} result:{}", end-begin,resultDataList);
    return resultDataList;
}

public void mysql30msTestAsync() {
    CompletableFuture<List<MysqlService.ResultData>> data =  mysqlService.getDataAsync();
    try {
        List<MysqlService.ResultData> result = data.get(3, TimeUnit.SECONDS);
        log.info("mysql30msTestAsync result:{}", result);
    } catch (Throwable throwable) {
        log.error("dataget exMsg:{}", throwable.getMessage(), throwable);
    }
}
仍存在的问题
  • 压测程序时问题仍未解决。
  • 通过jcmd导出线程栈后发现,虚拟线程仍进入MySQL查询逻辑,不符合预期。
{ 
  "tid": "8797977",
  "name": "TestHelloIServantObj-worker-v-8773083",
  "stack": [
     "java.base/java.lang.VirtualThread.parkNanos(VirtualThread.java:631)",
     "java.base/java.lang.System$2.parkVirtualThread(System.java:2648)",
     "java.base/jdk.internal.misc.VirtualThreads.park(VirtualThreads.java:67)",
     "java.base/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:267)",
     "java.base/java.util.concurrent.SynchronousQueue$TransferQueue.transfer(SynchronousQueue.java:704)",
     "java.base/java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:903)",
     "com.zaxxer.hikari.util.ConcurrentBag.borrow(ConcurrentBag.java:151)",
     "com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162)",
     "com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:144)",
     "com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:127)",
     "org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:160)",
     "org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:118)",
     "org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:81)",
     "org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:388)",
     "org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:476)",
     "org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:486)",
     "com.example.loomservlet.service.MysqlService.getData(MysqlService.java:48)",
     "com.example.loomservlet.service.MysqlService.lambda$getDataAsync$0(MysqlService.java:56)",
     "java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)",
     "java.base/java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy.rejectedExecution(ThreadPoolExecutor.java:2053)",
     "java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:841)",
     "java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1376)",
     "java.base/java.util.concurrent.CompletableFuture.asyncSupplyStage(CompletableFuture.java:1782)",
     "java.base/java.util.concurrent.CompletableFuture.supplyAsync(CompletableFuture.java:2005)",
     "com.example.loomservlet.service.MysqlService.getDataAsync(MysqlService.java:55)",
     "com.example.loomservlet.service.StressTestService.mysql30msTestAsync(StressTestService.java:62)",
     "com.example.loomservlet.service.StressTestService.funcDispatch(StressTestService.java:86)",
     "com.example.loomservlet.servant.MyFirstServantImpl.testFunc(MyFirstServantImpl.java:62)",
     "java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)",
     "java.base/java.lang.reflect.Method.invoke(Method.java:580)",
     "com.huya.taf.server.core.ServantHomeSkeleton.invoke(ServantHomeSkeleton.java:70)",
     "com.huya.taf.server.core.TafServerFilterChain.doRealInvoke(TafServerFilterChain.java:25)",
     "com.huya.taf.common.AbstractFilterChain.doFilter(AbstractFilterChain.java:38)",
     "com.huya.taf.trace.TraceServerFilter.doFilter(TraceServerFilter.java:55)",
     "com.huya.taf.common.AbstractFilterChain.doFilter(AbstractFilterChain.java:36)",
     "com.huya.taf.server.core.TafServantProcessor.process(TafServantProcessor.java:199)",
     "com.huya.taf.net.core.nio.WorkThread.run(WorkThread.java:95)",
     "java.base/java.lang.VirtualThread.run(VirtualThread.java:311)",
  ]
},

内容的提问来源于stack exchange,提问作者walker_fish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 07:04:52