【JDK19新特性】

JDK19

JDK 19 2022 年 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。开始有虚拟线程了

特性列表

405:Record Patterns (Preview)
422:Linux/RISC-V Port
424:Foreign Function & Memory API (Preview)
425:Virtual Threads (Preview)
426:Vector API (Fourth Incubator)
427:Pattern Matching for switch (Third Preview)
428:Structured Concurrency (Incubator)

Record Patterns (Preview)

对于record的 instanceof的模式匹配

record Point(int x, int y) {}
//old 
static void printSum(Object o) {
    if (o instanceof Point p) {
        int x = p.x();
        int y = p.y();
        System.out.println(x+y);
    }
}
// new 
static void printSum(Object o) {
    if (o instanceof Point p) {
        int x = p.x();
        int y = p.y();
        System.out.println(x+y);
    }
}
// 泛型
record Box<T>(T t) {}
static void test1(Box<Object> bo) {
    if (bo instanceof Box<Object>(String s)) {
        System.out.println("String " + s);
    }
}
static void test2(Box<Object> bo) {
    if (bo instanceof Box<String>(var s)) {
        System.out.println("String " + s);
    }
}

static void erroneousTest1(Box<Object> bo) {
    if (bo instanceof Box(var s)) {                 // Error
        System.out.println("I'm a box");
    }
}
static void erroneousTest2(Box b) {
    if (b instanceof Box(var t)) {                  // Error
        System.out.println("I'm a box");
    }
}

JEP 422: Linux/RISC-V Port

Linux/RISC-V 移植

JEP 424: Foreign Function & Memory API (Preview)

之前的incubator 变成preview API了;

例子

使用FFM API的一个简短示例,下面是Java代码,它获取C库函数radixsort的方法句柄,然后使用它对四个字符串进行排序,这些字符串在Java数组中开始运行(省略了一些细节)。因为FFM API是一个预览API,你必须在启用预览特性的情况下编译和运行代码,例如,javac——release 19——enable-preview…Java——enable-preview …

// 1. Find foreign function on the C library path
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle radixSort = linker.downcallHandle(
                             stdlib.lookup("radixsort"), ...);
// 2. Allocate on-heap memory to store four strings
String[] javaStrings   = { "mouse", "cat", "dog", "car" };
// 3. Allocate off-heap memory to store four pointers
SegmentAllocator allocator = SegmentAllocator.implicitAllocator();
MemorySegment offHeap  = allocator.allocateArray(ValueLayout.ADDRESS, javaStrings.length);
// 4. Copy the strings from on-heap to off-heap
for (int i = 0; i < javaStrings.length; i++) {
    // Allocate a string off-heap, then store a pointer to it
    MemorySegment cString = allocator.allocateUtf8String(javaStrings[i]);
    offHeap.setAtIndex(ValueLayout.ADDRESS, i, cString);
}
// 5. Sort the off-heap data by calling the foreign function
radixSort.invoke(offHeap, javaStrings.length, MemoryAddress.NULL, '\0');
// 6. Copy the (reordered) strings from off-heap to on-heap
for (int i = 0; i < javaStrings.length; i++) {
    MemoryAddress cStringPtr = offHeap.getAtIndex(ValueLayout.ADDRESS, i);
    javaStrings[i] = cStringPtr.getUtf8String(0);
}
assert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"});  // true

JEP 425: Virtual Threads (Preview)

向Java平台引入虚拟线程。虚拟线程是轻量级线程,可以显著减少编写、维护和观察高吞吐量并发应用程序的工作量。这是一个预览API。

最重要的特性,这个特性得开个单个文章讲

使用例子

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
// 或者
Thread thread = Thread.ofVirtual().name("duke").unstarted(runnable);

JEP 426: Vector API (Fourth Incubator)

向量api,继续Incubator

JEP 427: Pattern Matching for switch (Third Preview)

扩展大小写标签,除常量外,还包括模式和null;

扩展switch语句和switch表达式的选择器表达式允许的类型范围,以及允许可选的when子句跟在case标签后面。

为方便起见,我们还引入了带括号的模式。

// old
static void testFooBar(String s) {
    if (s == null) {
        System.out.println("Oops!");
        return;
    }
    switch (s) {
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}
// new
static void testFooBar(String s) {
    switch (s) {
        case null         -> System.out.println("Oops");
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}

JEP 428: Structured Concurrency (Incubator)

通过引入结构化并发的API来简化多线程编程。结构化并发将在不同线程中运行的多个任务视为单个工作单元,从而简化了错误处理和取消,提高了可靠性并增强了可观察性。这是一个正在孵化的API。

Response handle() throws ExecutionException, InterruptedException {
    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还是会在自己的线程继续运行,或者findUser需要运行很长时间,而当fetchOrder异常时,整个handle方法还是需要浪费时间等待findUser执行完,它阻塞在user.get()。为了更好地处理这种在异常场景下取消其他子任务,引入结构化并发来解决此问题,其主要是StructuredTaskScope这个类,它可以fork子任务,然后一起join或者一起cancel。

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());
    }
}

如果其中一个子任务失败了,则会取消另外一个在运行的任务。在scope.join()之后,可以使用resultNow()或者exceptionNow()来获取结果

其他参考

JDK 19 (openjdk.org)

jdk19 - Java19的新特性 - code-craft - SegmentFault 思否

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值