与平台线程一样,虚拟线程也是 java.lang.Thread 的一个实例对象。但是,虚拟线程并不依赖于特定的操作系统线程。
虚拟线程底层仍然在操作系统的线程上运行代码。但是与平台线程不相同的是,在平台线程中运行的代码调用阻塞 I/O 操作时,JVM 就会挂起该平台线程(也就会挂起操作系统线程),直到阻塞 I/O 可以恢复为止。
而在虚拟线程中调用阻塞 I/O 操作时,JVM 虽然也会挂起该虚拟线程,但是与平台线程不同的是,被挂起虚拟线程关联的操作系统线程是可以为其他虚拟线程继续服务的。
虚拟线程的实现方式与虚拟内存类似。为了模拟大量内存,操作系统将较大的虚拟地址空间映射到有限的 RAM。同样,为了模拟大量线程,Java 运行时将大量虚拟线程映射到少量操作系统线程。
因此与平台线程消耗的资源很多不同,虚拟线程在使用时只需要很少的内存资源。单个 JVM 就可以轻松创建数百万个虚拟线程。
使用虚拟线程是,通常建议调用堆栈不要过深,只执行单个 HTTP 客户端调用或单个 JDBC 查询即可。尽管虚拟线程支持线程局部变量和可继承的线程局部变量,但我们应该仔细考虑后再使用它们,因为单个 JVM 可能运行数百万个虚拟线程。
虚拟线程适合用于运行有大量阻塞 I/O 操作的任务,而不是长时间运行的 CPU 密集型任务。