How to yield the virtual thread?

123 views Asked by At
  • 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       },
0

There are 0 answers