当前版本 Loom
项目中协程使用并没有引入一个新的公开的虚拟线程VirtualThread
类,虽然真的存在 VirtualThread
,但这个类使用 default
修饰符,隐藏在java.lang
包中,并且 VirtualThread
是 Thread
的子类。协程的创建 API
位于 Thread
类中:
当前版本 Loom
项目中协程使用并没有引入一个新的公开的虚拟线程 VirtualThread
类,虽然真的存在 VirtualThread
,但这个类使用 default
修饰符,隐藏在 java.lang
包中,并且 VirtualThread
是 Thread
的子类。协程的创建 API
位于 Thread
类中:
使用此 API
创建协程如下:
public static void main(String[] args) {
Thread fiber = Thread.startVirtualThread(() -> System.out.println(“Hello Fiber”));
}
从当前的源码可知:
VirtualThread
会通过 Thread.currentThread()
获取父线程的调度器,如果在 main 方法运行,那么上面代码中的协程实例的父线程就是 main
线程
默认的调度器为系统创建的 ForkJoinPool
实例( VirtualThread.DEFAULT_SCHEDULER )
,输入的 Runnable
实例会被封装为RunContinuation
,最终由调度器执行
对于timed unpark
(正在阻塞,等待唤醒)的协程,使用系统创建的ScheduledExecutorService
实例进行唤醒
这个静态工厂方法创建完协程马上运行,返回的是协程实例
如果按照上面的 Thread.startVirtualThread()
方法去创建协程,显然无法定义协程的名称等属性。Loom
项目为 Thread
类引入了建造者模式,比较合理地解决了这个问题:
// 创建平台线程建造器,对应于Thread实例
public static Builder.OfPlatform ofPlatform() {
return new ThreadBuilders.PlatformThreadBuilder();
}
// 创建虚拟线程建造器,对应于VirtualThread
public static Builder.OfVirtual ofVirtual() {
return new ThreadBuilders.VirtualThreadBuilder();
}
简单说就是:
ofPlatform()
方法用于构建Thread
实例,这里的 Platform Thread (平台线程)
其实就是 JDK1.0
引入的线程实例,普通的用户线程
ofVirtual()
方法用于构建 VirtualThread
实例,也就是构建协程实例
这两个建造器实例的所有 Setter
方法链展开如下:
public static void main(String[] args) {
Thread.Builder.OfPlatform platformThreadBuilder = Thread.ofPlatform()
// 是否守护线程
.daemon(true)
// 线程组
.group(Thread.currentThread().getThreadGroup())
// 线程名称
.name(“thread-1”)
// 线程名称前缀 + 起始自增数字 => prefix + start,下一个创建的线程名称就是prefix + (start + 1)
// start > 0的情况下会覆盖name属性配置
.name(“thread-”, 1L)
// 是否启用ThreadLocal
.allowSetThreadLocals(false)
// 是否启用InheritableThreadLocal
.inheritInheritableThreadLocals(false)
// 设置优先级
.priority(100)
// 设置线程栈深度
.stackSize(10)
// 设置未捕获异常处理器
.uncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
}
});
// thread-1
Thread firstThread = platformThreadBuilder.unstarted(() -> System.out.println(“Hello Platform Thread First”));
// thread-2
Thread secondThread = platformThreadBuilder.unstarted(() -> System.out.println(“Hello Platform Thread Second”));
Thread.Builder.OfVirtual virtualThreadBuilder = Thread.ofVirtual()
// 协程名称
.name(“fiber-1”)
// 协程名称前缀 + 起始自增数字 => prefix + start,下一个创建的协程名称就是prefix + (start + 1)
// start > 0的情况下会覆盖name属性配置
.name(“fiber-”, 1L)
// 是否启用ThreadLocal
.allowSetThreadLocals(false)
// 是否启用InheritableThreadLocal
.inheritInheritableThreadLocals(false)
// 设置调度器,Executor实例,也就是调度器是一个线程池,设置为NULL会使用VirtualThread.DEFAULT_SCHEDULER
.scheduler(null)
// 设置未捕获异常处理器
.uncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
}
});
// fiber-1
Thread firstFiber = virtualThreadBuilder.unstarted(() -> System.out.println(“Hello Platform Virtual First”));
// fiber-2
Thread secondFiber = virtualThreadBuilder.unstarted(() -> System.out.println(“Hello Platform Virtual Second”));
}
这里可以发现一点,就是 建造器是可以复用的 。如果想用建造器创建同一批参数设置相同的线程或者协程,可以设置 name(String prefix, long start)
方法,定义线程或者协程的名称前缀和一个大于等于 0 的数字,反复调用 Builder#unstarted(Runnable task)
方法就能批量创建线程或者协程,名称就设置为 prefix + start
、 prefix + (start + 1)
、 prefix + (start + 2)
以此类推。协程创建基本就是这么简单,运行的话直接调用 start()
方法:
public class FiberSample2 {
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!**
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!