在长期支持版本17之后,这个新的java版本为那些其他语言忽略或难解决的问题,提供了些简洁易用的方案。
并发
结构化任务域(structured task scope),一个全新的代码块形式,专注于处理并发场景。
Response handle() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> findUser());
Future<Integer> order = scope.fork(() -> fetchOrder());
scope.join(); // Join both forks
scope.throwIfFailed(); // ... and propagate errors
// Here, both forks have succeeded, so compose their results
return new Response(user.resultNow(), order.resultNow());
}
}
对比下以前的写法
Response handle() throws ExecutionException, InterruptedException {
// esvc 是一个ExecutorService
Future<String> user = esvc.submit(() -> findUser());
Future<Integer> order = esvc.submit(() -> fetchOrder());
String theUser = user.get(); // Join findUser
int theOrder = order.get(); // Join fetchOrder
return new Response(theUser, theOrder);
}
优势在于findUser()
和fetchOrder()
各自出现错误时,可以节约更多的资源,因为它可以立刻终止所有子任务,放以前,fetchOrder()
哪怕一开始就有错,也要在user.get()
阻塞完后报错。另外这种写法,使得代码块成为一个单元,要么成功,要么失败。
启用
这玩意是在“恒温箱”模块里(incubator module),听这名字就知道属于孵化期的东西,因此它是默认排除的,使用它需要手动设置一些东西,这里以 IDEA 为例。
在这个位置配置javac的特殊参数,由于我不想污染其他项目,就只针对某个模块配置了。
--release 19 --enable-preview --add-modules=jdk.incubator.concurrent
然后是设置运行时的vm参数
--enable-preview --add-modules jdk.incubator.concurrent
不建议直接改idea.exe.vmoptions
的设置,你万一用的不是这个版本的jdk就炸了
简化record类型的使用
直接上代码感受下
record Point(int x, int y){}
void printSum(Object o){
if(o instanceof Point(int x, int y)){
System.out.println(x+y);
}
}
虚拟线程
提供了一个轻量化的并发方案,这些虚拟线程由JDK管理,可以在同一个线程上管理大量的虚拟线程,这使得你可以大量地使用它来进行并发,而不是像以前一样创建线程。
使用例子:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
} // executor.close() is called implicitly, and waits
此处Executors
增加了一个获取虚拟线程的静态方法。