基础[Java] java新特性之虚拟线程---概念理解

108 阅读3分钟

我们知道一个进程至少包含一个线程,CPU调度的最小单位也是线程,但是为什么我们需要使用虚拟线程呢,在我看来虚拟线程表示的只不过是异步的特性,这个特性具体体现在对大量IO密集型操作的性能提升,我把它对标为Javascript中的Promise,Javascript runtime属于单线程工作,而异步能力靠的是通过libuv实现event loop异步调度.而java为什么需要实现虚拟线程呢?

我们知道一个程序可以创建多个线程执行,而线程的执行所带来的直接效果是提升了程序的并行能力,但是过多的线程会带来CPU调度线程的切换的性能损耗.所以这个时候就需要一种不需要多次切换线程也能达到执行并发的能力这里说并发是因为线程内程序的执行是顺序的,而非并列执行,可以使用一个线程处理多个任务,非常适合IO密集型操作

下图展示了并发与并行的区别

image.png

image.png

  1. 线程切换上下文的开销

线程切换主要开销在:

  1. 切换页表全局目录
  2. 切换内核态堆栈
  3. 切换硬件上下文
  4. 刷新TLB页面缓存
  5. 调度代码执行

一般CPU的线程切换依赖于定时器中断,通过定时器中断动态调度处于就绪态的任务

间接开销:根据数据的局部性原理,对于数组等数据满足空间局部性,对于程序代码满足时间局部性,如果线程频繁切换,会因频繁切换上下文导致该优化机制反而成为了负担.

那么我们就可以理解虚拟线程了,对于目前的web应用开发,除了一些特殊操作如生成excel,电子合同等需要占用CPU的文件资源,其余的还是以IO的形式接收处理,若一直使用真实线程,则线程之间的开销反而比程序运行时间还多,得不偿失了,目前典型的IO场景有

  • 读写本地文件
  • 网络IO
  • 数据库IO(本质上也是网络io,大多数实现数据库提供的标准)

回归主题虚拟线程本身也是一个线程,只不过他的执行是依靠普通线程进行调度,使多个IO型操作可以被虚拟线程执行并进行调度,当IO操作进入pedding时挂起并执行其它任务.而当IO操作完成了等待,那么它就重新回归就绪,并等待调度.(这些理解结合了JavaScript event loop)

----更新----

觉得这个特性会利好mybatis等ORM框架或druid数据库连接池,将原先的线程级别的IO操作转化为虚拟线程级别的IO操作,性能和资源占用比应该会大幅提升。