Thread[#93,ForkJoinPool-1-worker-4,5,CarrierThreads]
java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:185)
java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:393)
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:408)
java.base/sun.nio.ch.Poller.pollIndirect(Poller.java:137)
java.base/sun.nio.ch.Poller.poll(Poller.java:102)
java.base/sun.nio.ch.Poller.poll(Poller.java:87)
java.base/sun.nio.ch.NioSocketImpl.park(NioSocketImpl.java:175)
java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:280)
java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:304)
java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:346)
java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:796)
java.base/java.net.Socket$SocketInputStream.read(Socket.java:1099)
com.mysql.cj.protocol.ReadAheadInputStream.fill(ReadAheadInputStream.java:107)
com.mysql.cj.protocol.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:150)
com.mysql.cj.protocol.ReadAheadInputStream.read(ReadAheadInputStream.java:180) <== monitors:1
java.base/java.io.FilterInputStream.read(FilterInputStream.java:119)
com.mysql.cj.protocol.FullReadInputStream.readFully(FullReadInputStream.java:64)
com.mysql.cj.protocol.a.SimplePacketReader.readHeaderLocal(SimplePacketReader.java:81)
com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:63)
com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:45)
com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:52)
com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:41)
com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:54)
com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:44)
com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:576)
com.mysql.cj.protocol.a.NativeProtocol.checkErrorMessage(NativeProtocol.java:762)
com.mysql.cj.protocol.a.NativeProtocol.sendCommand(NativeProtocol.java:701)
com.mysql.cj.protocol.a.NativeProtocol.sendCommand(NativeProtocol.java:156)
com.mysql.cj.NativeSession.ping(NativeSession.java:733)
com.mysql.cj.jdbc.ConnectionImpl.pingInternal(ConnectionImpl.java:1478)
com.mysql.cj.jdbc.ConnectionImpl.isValid(ConnectionImpl.java:2516) <== monitors:1
com.zaxxer.hikari.pool.PoolBase.isConnectionDead(PoolBase.java:157
一个非常简单的答案:不要在虚拟线程上调用 mySQL JDBC Connector 以避免固定。当然,除非您要重写 mySQL JDBC Connector。 Java 充满了
synchronized
,即使是像 java.util.concurrent.ConcurrentHashMap
这样流行且优秀的多线程工具也有它,不可能一夜之间用非固定替代方案取代所有 synchronized
和其他固定操作。 Project Loom 和虚拟线程还不够稳定和成熟,不足以保证如此大规模的重构。因此,您能做的最好的事情就是避免使用虚拟线程来频繁固定代码(虽然偶尔的固定可能是可以容忍的)
另一方面,如果虚拟线程被固定,它可能不会(或者不应该,如果不是 JDK bug)导致您的系统无限期挂起或死机或类似的情况。当该虚拟线程保持固定状态时,相应的 Carrier(平台)线程将被从 Carrier 线程池中排除。当固定动作时,例如
Thread.sleep
,完成,固定的螺纹应该变为未固定的。当然,固定会降低虚拟线程机器的性能,并且本身就是对它的滥用,但它不应该成为系统死亡的原因。 (除非你对事情“强调”到了不可能的程度,这可能是也可能不是你的个人情况)。