- It seems that mysql-connect-java is not compatible with virtual thread. When i use -Djdk.tracePinnedThreads=full, I found some pinned stack trace.
- So my question is how to fix this problem? I have try to replace synchronized to ReentrantLock. But it is still not work.
- So i think another method is to yield the virtual thread to another platform thread.
- I use the springmvc handler to test this scene. spring.threads.virtual.enabled = true. The virtual thread is create like: Thread.ofVirtual().name("testvt").start(task); The source code you can see in tomcat:https://github.com/apache/tomcat/blob/10.1.x/java/org/apache/tomcat/util/compat/Jre21Compat.java
My try
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);
}
}
Still problem
- When I stress the program, it still not ok.
- I dump the thread stack by jcmd.
- It seems that virtual thread run into the mysql query logic. That is not my expect.
238519 {
238520 "tid": "8797977",
238521 "name": "TestHelloIServantObj-worker-v-8773083",
238522 "stack": [
238523 "java.base\/java.lang.VirtualThread.parkNanos(VirtualThread.java:631)",
238524 "java.base\/java.lang.System$2.parkVirtualThread(System.java:2648)",
238525 "java.base\/jdk.internal.misc.VirtualThreads.park(VirtualThreads.java:67)",
238526 "java.base\/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:267)",
238527 "java.base\/java.util.concurrent.SynchronousQueue$TransferQueue.transfer(SynchronousQueue.java:704)",
238528 "java.base\/java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:903)",
238529 "com.zaxxer.hikari.util.ConcurrentBag.borrow(ConcurrentBag.java:151)",
238530 "com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:162)",
238531 "com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:144)",
238532 "com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:127)",
238533 "org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:160)",
238534 "org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:118)",
238535 "org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:81)",
238536 "org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:388)",
238537 "org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:476)",
238538 "org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:486)",
238539 "com.example.loomservlet.service.MysqlService.getData(MysqlService.java:48)",
238540 "com.example.loomservlet.service.MysqlService.lambda$getDataAsync$0(MysqlService.java:56)",
238541 "java.base\/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)",
238542 "java.base\/java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy.rejectedExecution(ThreadPoolExecutor.java:2053)",
238543 "java.base\/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:841)",
238544 "java.base\/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1376)",
238545 "java.base\/java.util.concurrent.CompletableFuture.asyncSupplyStage(CompletableFuture.java:1782)",
238546 "java.base\/java.util.concurrent.CompletableFuture.supplyAsync(CompletableFuture.java:2005)",
238547 "com.example.loomservlet.service.MysqlService.getDataAsync(MysqlService.java:55)",
238548 "com.example.loomservlet.service.StressTestService.mysql30msTestAsync(StressTestService.java:62)",
238549 "com.example.loomservlet.service.StressTestService.funcDispatch(StressTestService.java:86)",
238550 "com.example.loomservlet.servant.MyFirstServantImpl.testFunc(MyFirstServantImpl.java:62)",
238551 "java.base\/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)",
238552 "java.base\/java.lang.reflect.Method.invoke(Method.java:580)",
238553 "com.huya.taf.server.core.ServantHomeSkeleton.invoke(ServantHomeSkeleton.java:70)",
238554 "com.huya.taf.server.core.TafServerFilterChain.doRealInvoke(TafServerFilterChain.java:25)",
238555 "com.huya.taf.common.AbstractFilterChain.doFilter(AbstractFilterChain.java:38)",
238556 "com.huya.taf.trace.TraceServerFilter.doFilter(TraceServerFilter.java:55)",
238557 "com.huya.taf.common.AbstractFilterChain.doFilter(AbstractFilterChain.java:36)",
238558 "com.huya.taf.server.core.TafServantProcessor.process(TafServantProcessor.java:199)",
238559 "com.huya.taf.net.core.nio.WorkThread.run(WorkThread.java:95)",
238560 "java.base\/java.lang.VirtualThread.run(VirtualThread.java:311)"
238561 ]
238562 }
238563 ],
238564 "threadCount": "6044"
238565 },