如何让虚拟线程让出执行权?解决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
相关产品推荐
相关产品推荐

