Java 虚拟机在退出时会等待所有的平台线程线程结束, 但是不会等待虚拟线程们结束.
注意: 创建的平台线程 Thread.daemon
默认是 false, 当其被修改为 true 时也不会被等待.
如下代码
public static void main(String[] args) throws InterruptedException {
System.out.println("- Hello World!");
// start a platform thread
Thread platform = Thread.ofPlatform().start(() -> {
try {
TimeUnit.SECONDS.sleep(8);
} catch (InterruptedException ignore) {
System.out.println("platform thread Interrupted!");
}
long id = Thread.currentThread().threadId();
System.out.println("+ Hello World from platform thread " + id);
});
// start a virtual thread
Thread virtual = Thread.ofVirtual().start(() -> {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException ignore) {
System.out.println("virtual thread Interrupted!");
}
long id = Thread.currentThread().threadId();
System.out.println("+ Hello World from virtual thread " + id);
});
// wait for the threads to complete
// platform.join();
// virtual.join();
TimeUnit.SECONDS.sleep(5);
// print the thread state
System.out.println("- platform thread state is " + platform.getState());
System.out.println("- virtual thread state is " + virtual.getState());
System.out.println("- Goodbye World!");
}
总是会输出
- Hello World!
- platform thread state is TIMED_WAITING
- virtual thread state is WAITING
- Goodbye World!
+ Hello World from platform thread 21
为什么?
从Java层来看. 因为 Virtual Thead 总是为 daemon thread. 下面是 Thread#isDaemon()
在 JDK21 中的源码
/**
* Tests if this thread is a daemon thread.
* The daemon status of a virtual thread is always {@code true}.
*
* @return {@code true} if this thread is a daemon thread;
* {@code false} otherwise.
* @see #setDaemon(boolean)
*/
public final boolean isDaemon() {
if (isVirtual()) {
return true;
} else {
return holder.daemon;
}
}
同时, Virtual Thead 的 daemon 属性不可被修改, 尝试调用一个虚拟线程的Thread#setDaemon(boolean on)
将会抛出 'false' not legal for virtual threads
另外可以从Thead 的 State 中看出, 平台线程调用 sleep 之后 状态为 TIMED_WAITING
而 虚拟线程的状态为 WAITING
更深层的原理这里不再深究, 可以肯定的是和虚拟线程的调度器(们)的策略有关.