JDK21來了!附重要更新說明

来源:https://www.cnblogs.com/dafanjoy/archive/2023/09/18/17709944.html
-Advertisement-
Play Games

JDK21 計劃23年9月19日正式發佈,雖然一直以來都是“版本隨便出,換 8 算我輸”,但這麼多年這麼多版本的折騰,如果說之前的 LTS版本JDK17你還覺得不香,那 JDK21還是有必要關註一下,因為會有一批重要更新發佈到生產環境中,特別是千呼萬喚的虛擬線程,雖然說這東西我感覺不需要的用不到,需 ...


JDK21 計劃23年9月19日正式發佈,雖然一直以來都是“版本隨便出,換 8 算我輸”,但這麼多年這麼多版本的折騰,如果說之前的 LTS版本JDK17你還覺得不香,那 JDK21還是有必要關註一下,因為會有一批重要更新發佈到生產環境中,特別是千呼萬喚的虛擬線程,雖然說這東西我感覺不需要的用不到,需要的早都轉go了,哈哈,但作為近幾年JDK一個“重大”的更新,在實際開發應用中還是是有很大價值的。所以這篇文章主要提取了這次更新中個人感覺比較有價值的幾點做個基本的介紹,想要嘗鮮的同學可以看下。

Visual Threads (虛擬線程) -JEP 444

先看下官方對虛擬線程(Visual Threads)描述:

Today, every instance of java.lang.Thread in the JDK is a platform thread. A platform thread runs Java code on an underlying OS thread and captures the OS thread for the code's entire lifetime. The number of platform threads is limited to the number of OS threads.

virtual thread is an instance of java.lang.Thread that runs Java code on an underlying OS thread but does not capture the OS thread for the code's entire lifetime. This means that many virtual threads can run their Java code on the same OS thread, effectively sharing it. While a platform thread monopolizes a precious OS thread, a virtual thread does not. The number of virtual threads can be much larger than the number of OS threads.

Virtual threads are a lightweight implementation of threads that is provided by the JDK rather than the OS. They are a form of user-mode threads, which have been successful in other multithreaded languages (e.g., goroutines in Go and processes in Erlang). User-mode threads even featured as so-called "green threads" in early versions of Java, when OS threads were not yet mature and widespread. However, Java's green threads all shared one OS thread (M:1 scheduling) and were eventually outperformed by platform threads, implemented as wrappers for OS threads (1:1 scheduling). Virtual threads employ M:N scheduling, where a large number (M) of virtual threads is scheduled to run on a smaller number (N) of OS threads.

總結下就是之前java中的線程是“platform thread”即平臺線程,它由操作系統線程為基礎,按照1:1的模式調度,這導致線程的創建與執行都是很耗資源的,同時數量也受系統的約束;但新的虛擬線程則是由JDK提供,你可以把它看作是在平臺線程基礎上創建的“一批”線程,它們有效地共用所屬的平臺線程也就是操作系統線程的資源,從而提升系統利用率,並不受數量限制。

目標描述:

1、Enable server applications written in the simple thread-per-request style to scale with near-optimal hardware utilization.

可以每個請求開啟一個虛擬線程,實現簡單直接的同時可以最大程度的提升硬體利用率;

2、Enable existing code that uses the java.lang.Thread API to adopt virtual threads with minimal change.

之前的多線程實現代碼可以在較小的改動下完成向虛擬線程的遷移;

3、Enable easy troubleshooting, debugging, and profiling of virtual threads with existing JDK tools.

使用現有JDK工具可以完成虛擬線程的代碼調試、分析與問題定位;

說白了就是現在我們不用怎麼改代碼就可以創建一個輕量級的虛擬線程,實現簡單同時還能夠充分發揮硬體性能。

一個簡單的代碼示例

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  // executor.close() is called implicitly, and waits

SequencedCollection Interface(順序集合 介面)

兄弟們,作為一個天天CRUD,CPU跑不滿20%的程式員, 相比上面的虛擬線程,這次關於集合類介面的更新我感覺更實在一些

JDK21中我們常用的Set、List、Deque與Map集合類分別繼承實現了SequencedCollection、 SequencedMap 介面,為我們執行一些順序性操作比如獲取頭尾值提供了各類介面方法

繼承關係如下圖所示:

介面定義如下

interface SequencedCollection<E> extends Collection<E> {
    // new method
    SequencedCollection<E> reversed();
    // methods promoted from Deque
    void addFirst(E);
    void addLast(E);
    E getFirst();
    E getLast();
    E removeFirst();
    E removeLast();
}
interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
    SequencedSet<E> reversed();    // covariant override
}
interface SequencedMap<K,V> extends Map<K,V> {
    // new methods
    SequencedMap<K,V> reversed();
    SequencedSet<K> sequencedKeySet();
    SequencedCollection<V> sequencedValues();
    SequencedSet<Entry<K,V>> sequencedEntrySet();
    V putFirst(K, V);
    V putLast(K, V);
    // methods promoted from NavigableMap
    Entry<K, V> firstEntry();
    Entry<K, V> lastEntry();
    Entry<K, V> pollFirstEntry();
    Entry<K, V> pollLastEntry();
}

Record Patterns (記錄模式)-JEP 440

這個更新主要簡化了類型判斷與賦值的使用,類型判斷後無需顯式強制轉換且如果模式匹配,變數被初始化為要匹配的模板值, 這個說起來比較拗口,結合代碼大家理解下,我感覺還是挺有用的,這裡我把JDK8 JDK17 JDK21 的實現進行一個對比,大家就明白了。

// As of Java 8
record Point(int x, int y) {}

static void printSum(Object obj) {
    if (obj instanceof Point) {
        Point p = (Point) obj;
        int x = p.x();
        int y = p.y();
        System.out.println(x+y);
    }
}
// As of Java 16
record Point(int x, int y) {}

static void printSum(Object obj) {
    if (obj instanceof Point p) {
        int x = p.x();
        int y = p.y();
        System.out.println(x+y);
    }
}
// As of Java 21
static void printSum(Object obj) {
    if (obj instanceof Point(int x, int y)) {
        System.out.println(x+y);
    }
}

Pattern Matching for switch (switch模式匹配) – JEP 441

switch 的模式匹配可以與Record Patterns結合使用 允許在任何對象上制定 switch 語句和表達式。看一下代碼例子:

static String formatterPatternSwitch(Object obj) {
    return switch (obj) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %f", d);
        case String s  -> String.format("String %s", s);
        case Position(int x, int y)   -> String.format("String %s,String %s", x,y);
        default        -> obj.toString();
    };
}

同時當編譯器判斷所有分支都已涵蓋時,switch不再需要分支default,如下麵的代碼

void flyJava21(Direction direction) { 
    switch (direction) {
       case CompassDirection.NORTH -> System.out.println("Flying north"); 
       case CompassDirection.SOUTH -> System.out.println("Flying south");
       case CompassDirection.EAST -> System.out.println("Flying east");
       case CompassDirection.WEST -> System.out.println("Flying west"); 
       case VerticalDirection.UP -> System.out.println("Gaining altitude"); 
       case VerticalDirection.DOWN -> System.out.println("Losing altitude"); 
    } 
}

Generational ZGC(分代式 ZGC) -JEP 439

主要是增加了對分代的支持,提高垃圾回收的性能,看下整體描述

To ensure a smooth succession, we will initially make Generational ZGC available alongside non-generational ZGC. The -XX:+UseZGC command-line option will select non-generational ZGC; to select Generational ZGC, add the -XX:+ZGenerational option:

使用命令行選項 -XX:+UseZGC 將選擇非分代式 ZGC;要選擇分代式 ZGC,需要添加 -XX:+ZGenerational 選項。

$ java -XX:+UseZGC -XX:+ZGenerational ...

In a future release we intend to make Generational ZGC the default, at which point -XX:-ZGenerational will select non-generational ZGC. In an even later release we intend to remove non-generational ZGC, at which point the ZGenerational option will become obsolete.

總結就是當前版本中如果想使用ZGC,命令行選項增加 -XX:+UseZGC,但預設是非分代式GC;要使用分代式ZGC ,需要改為 $ java -XX:+UseZGC -XX:+ZGenerational ,而在後續的版本中會預設改為分代GC。

以上就是JDK21版本中我感覺一些有價值的更新,如果大家希望能夠更進一步的瞭解還是要去官網https://openjdk.org/projects/jdk/21/ 自行查看,併在發佈之後在使用中實際驗證。

之所以有這次總結,主要還是有感於java近年來受到其他各類語言的衝擊,頗有垂垂老矣的感覺,讓我這個C#出身的javaer又想起了一段不好的回憶,哈哈,所以看看這次的更新是否能給點力, 當前java語言的下行趨勢也可以說是國內IT行業興衰起伏的一個側面寫照,當然作為一個提供生產力的編程語言,圍繞java建立起的整個完整、穩定、強大的生態仍然會在它適合的領域起到重要的作用,這是一時半會無法改變的,但你指望靠它乾到退休估計連收了學費的培訓機構也不敢這樣說,程式員的職業壽命從來不是某種編程語言決定的。最後我還是想說入行的菜鳥才糾結於語言優劣,成熟老手知道這早有定論,讓我們大聲喊出:   

                                     "PHP是最好的語言"

這不是玩梗,因為從某種角度上講: 

                                 "生產力才是決定語言生死的關鍵"
  •  
  •  
  •  參考資料:https://openjdk.org/projects/jdk/21/
  •  
  •  

   關註微信公眾號,查看更多技術文章。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 變數 變數是用於存儲數據值的容器。 創建變數 Python沒有用於聲明變數的命令。 變數在您第一次為其分配值時被創建。 示例 x = 5 y = "John" print(x) print(y) 變數不需要聲明為特定類型,並且甚至在設置後可以更改類型。 示例 x = 4 # x的類型為int x = ...
  • 0 前言 一般初學者學習編碼和[錯誤處理]時,先知道[編程語言]有一種處理錯誤的形式或約定(如Java就拋異常),然後就開始用這些工具。但卻忽視這問題本質:處理錯誤是為了寫正確程式。可是 1 啥叫“正確”? 由解決的問題決定的。問題不同,解決方案不同。 如一個web介面接受用戶請求,參數age,也許 ...
  • 什麼是裝飾器,它們如何被使用,以及我們如何利用它們來構建代碼。我們將看到裝飾器是如何成為一個強大的工具,可以用來為我們的應用程式添加功能,並且可以在Python編程語言中找到。 裝飾器順序 在Python中,裝飾器是一個特殊的函數,可以修改另一個函數的行為。裝飾器是一種設計模式,它在不改變現有對象結 ...
  • dataclass 到 Python 中的 JSON JavaScript Object Notation或JSON表示使用編程語言中的文本組成的腳本(可執行)文件來存儲和傳輸數據。 Python通過JSON內置模塊支持JSON。因此,我們在Python腳本中導入JSON包,以利用這一能力。 JSO ...
  • 前言 很多時候,由於種種不可描述的原因,我們需要針對單個介面實現介面限流,防止訪問次數過於頻繁。這裡就用 redis+aop 實現一個限流介面註解 @RedisLimit 代碼 點擊查看RedisLimit註解代碼 import java.lang.annotation.*; /** * 功能:分佈 ...
  • 對重寫代碼說不。 以下為譯文: 1、重寫代碼消耗了12個月! 我們從頭開始重寫代碼浪費的時間。 你能想象在軟體行業,12個月的時間沒有任何新產品推出,沒有任何新版本更新嗎? 真的,我不由自主地問自己這個問題: 在這個快速發展的世界里,12月的時間能讓我們做多少事情? “2015年1月20日,星期二, ...
  • Nacos 2.x版本增加了GRPC服務介面和客戶端,極大的提升了Nacos的性能,本文將簡單介紹grpc-java的使用方式以及Nacos中集成GRPC的方式。 grpc-java GRPC是google開源的、以protobuf作為序列化方式、以http2作為通信協議的高性能rpc框架。 grp ...
  • 1.什麼是權重比例 權重比例計算即將各數值乘以相應的權數,然後加總求和得到總體值,再除以總的單位數。 如何計算 有一個對象集合為[A,B,C,D,E,F,G,H,I,J],其對象的全紅 總權重為10 每一個對象的權重為1/10=0.1 2.什麼是權重覆蓋區域 權重覆蓋區域是對象在整體權重範圍中的鎖分 ...
一周排行
    -Advertisement-
    Play Games
  • 1、預覽地址:http://139.155.137.144:9012 2、qq群:801913255 一、前言 隨著網路的發展,企業對於信息系統數據的保密工作愈發重視,不同身份、角色對於數據的訪問許可權都應該大相徑庭。 列如 1、不同登錄人員對一個數據列表的可見度是不一樣的,如數據列、數據行、數據按鈕 ...
  • 前言 上一篇文章寫瞭如何使用RabbitMQ做個簡單的發送郵件項目,然後評論也是比較多,也是準備去學習一下如何確保RabbitMQ的消息可靠性,但是由於時間原因,先來說說設計模式中的簡單工廠模式吧! 在瞭解簡單工廠模式之前,我們要知道C#是一款面向對象的高級程式語言。它有3大特性,封裝、繼承、多態。 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 介紹 Nodify是一個WPF基於節點的編輯器控制項,其中包含一系列節點、連接和連接器組件,旨在簡化構建基於節點的工具的過程 ...
  • 創建一個webapi項目做測試使用。 創建新控制器,搭建一個基礎框架,包括獲取當天日期、wiki的請求地址等 創建一個Http請求幫助類以及方法,用於獲取指定URL的信息 使用http請求訪問指定url,先運行一下,看看返回的內容。內容如圖右邊所示,實際上是一個Json數據。我們主要解析 大事記 部 ...
  • 最近在不少自媒體上看到有關.NET與C#的資訊與評價,感覺大家對.NET與C#還是不太瞭解,尤其是對2016年6月發佈的跨平臺.NET Core 1.0,更是知之甚少。在考慮一番之後,還是決定寫點東西總結一下,也回顧一下.NET的發展歷史。 首先,你沒看錯,.NET是跨平臺的,可以在Windows、 ...
  • Nodify學習 一:介紹與使用 - 可樂_加冰 - 博客園 (cnblogs.com) Nodify學習 二:添加節點 - 可樂_加冰 - 博客園 (cnblogs.com) 添加節點(nodes) 通過上一篇我們已經創建好了編輯器實例現在我們為編輯器添加一個節點 添加model和viewmode ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...
  • 類型檢查和轉換:當你需要檢查對象是否為特定類型,並且希望在同一時間內將其轉換為那個類型時,模式匹配提供了一種更簡潔的方式來完成這一任務,避免了使用傳統的as和is操作符後還需要進行額外的null檢查。 複雜條件邏輯:在處理複雜的條件邏輯時,特別是涉及到多個條件和類型的情況下,使用模式匹配可以使代碼更 ...
  • 在日常開發中,我們經常需要和文件打交道,特別是桌面開發,有時候就會需要載入大批量的文件,而且可能還會存在部分文件缺失的情況,那麼如何才能快速的判斷文件是否存在呢?如果處理不當的,且文件數量比較多的時候,可能會造成卡頓等情況,進而影響程式的使用體驗。今天就以一個簡單的小例子,簡述兩種不同的判斷文件是否... ...
  • 前言 資料庫併發,數據審計和軟刪除一直是數據持久化方面的經典問題。早些時候,這些工作需要手寫複雜的SQL或者通過存儲過程和觸發器實現。手寫複雜SQL對軟體可維護性構成了相當大的挑戰,隨著SQL字數的變多,用到的嵌套和複雜語法增加,可讀性和可維護性的難度是幾何級暴漲。因此如何在實現功能的同時控制這些S ...