经过jdk19和jdk20两次预览,在jdk21中虚拟线程正式成为api,由之前的1对1调用系统线程升级到大量虚拟线程对应有限数量系统线程,可以极大的提高并发性能,提高系统线程和cpu的利用率;
主要是对Thread类进行增强,增加了许多新的方法用于处理虚拟线程,例如isVirtual()判断线程是否是虚拟线程,但之前的已经存在的方法没有太大的变动,构造方法也没有增加,之前的功能不会受到影响;
创建虚拟线程的方法:
1、通过Executors的newVirtualThreadPerTaskExecutor()方法创建,使用方法跟之前的Executor一样:
@Test
void test() {
var executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(() -> {
System.out.println("executor virtual thread");
});
}
![]()
2、使用Thread.Builder创建一批相同属性的线程,Thread类新增了ofVirtual()和ofPlatform()方法用于生成虚拟线程和系统平台线程的Builder,Builder的name()方法可以设置线程名称,uncaughtExceptionHandler()方法可以设置未捕获异常,start()方法可以直接启动线程,unstarted()方法可以返回一个Thread对象用户自己决定何时启动,还有一些方法例如daemon()、group()、priority()、stackSize()是ofPlatform()平台线程特有的方法,虚拟线程无法设置的参数:
@Test
void test2() {
Thread.ofVirtual().name("abc").start(() -> {
System.out.println("Thread.ofVirtual:" + Thread.currentThread().getName());
});
Thread unstartedThread = Thread.ofVirtual().name("UnstartedThread").uncaughtExceptionHandler((t,e)->{}).unstarted(() -> {
Thread currentT = Thread.currentThread();
System.out.println("thread:%s state:%s isvirtual:%s".formatted(
currentT.getName(), currentT.getState(), currentT.isVirtual()));
});
unstartedThread.start();
OfPlatform builder = Thread.ofPlatform()
.name("platformThread_", 100) // 名字前缀+起始编号
// .daemon(false) // 平台线程特有,虚拟线程全是守护线程
// .group(null) // 平台线程特有,虚拟线程group名字固定为VirtualThreads
// .priority(0) // 平台线程特有,虚拟固定为Thread.NORM_PRIORITY
// .stackSize(100)
.uncaughtExceptionHandler((t, e) -> {
System.out.println("线程:%s 未捕获异常:%s".formatted(t, e));
});
builder.start(() -> {System.out.println(Thread.currentThread().getName());});
builder.start(() -> {System.out.println(Thread.currentThread().getName());});
builder.start(() -> {System.out.println(Thread.currentThread().getName());int i = 1/0;});
}

3、使用Thread的startVirtualThread()直接快速创建并运行虚拟线程:
@Test
void test3() {
Thread.startVirtualThread(() -> {
System.out.println("---" + Thread.currentThread());
Map<Thread, StackTraceElement[]> allPlatformThread = Thread.getAllStackTraces(); // 全部平台线程,非全部线程(平台、虚拟)
allPlatformThread.keySet().forEach(System.out::println);
});
}

需要注意的地方:
1、虚拟线程是大量的和低成本的,不需要池化;
2、有两种情况虚拟线程阻塞不会释放平台线程:使用synchronized修饰时和调用native方法或者foreign函数时,推荐使用java.util.concurrent.locks.ReentrantLock处理;
3、Thread的public构造方法无法创建虚拟线程,虚拟线程全是守护线程,优先级固定为Thread.NORM_PRIORITY,没有线程组,getThreadGroup()也只会返回一个固定的叫VirtualThreads的组;
4、Thread.getAllStackTraces()返回的是平台级线程,并非平台线程和虚拟线程全部的线程;
549

被折叠的 条评论
为什么被折叠?



