中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

引擎網(wǎng)站推廣法怎么做google下載app

引擎網(wǎng)站推廣法怎么做,google下載app,做設(shè)計(jì)去哪些網(wǎng)站下載素材,上杭網(wǎng)站建設(shè)工程 | JOSH LONG | 0條評(píng)論 Java 22發(fā)布快樂(lè)! Java 22 是一個(gè)重大的進(jìn)步,是一個(gè)值得升級(jí)版本。有一些重大的最終發(fā)布功能,如 Project Panama及一系列更優(yōu)秀的預(yù)覽功能。我不可能覆蓋它們?nèi)?amp;#xff0c;但我確實(shí)想談?wù)勎易钕矏?ài)的一些。我們…

工程 | JOSH LONG | 0條評(píng)論

Java 22發(fā)布快樂(lè)!

Java 22 是一個(gè)重大的進(jìn)步,是一個(gè)值得升級(jí)版本。有一些重大的最終發(fā)布功能,如 Project Panama及一系列更優(yōu)秀的預(yù)覽功能。我不可能覆蓋它們?nèi)?#xff0c;但我確實(shí)想談?wù)勎易钕矏?ài)的一些。我們將會(huì)涉及到許多功能。如果你想在家里跟著做,代碼在這。

我愛(ài)Java 22,當(dāng)然,我也愛(ài) GraalVM,它們都在發(fā)布了新版本!Java 當(dāng)然是我們最喜愛(ài)的運(yùn)行時(shí)和語(yǔ)言,而 GraalVM 是一個(gè)高性能的 JDK 發(fā)行版,它支持更多語(yǔ)言并允許提前編譯(它們被稱(chēng)為 GraalVM native images)。GraalVM 包含了 Java 22 新版的所有好東西,還有一些額外的工具,所以我總是推薦下載那個(gè)版本。我特別感興趣的是 GraalVM native image 的能力。生成的二進(jìn)制文件幾乎可以立即啟動(dòng),并且與它們的 JRE 相比,消耗的 RAM 明顯少。GraalVM 不是新事物,但值得記住的是,Spring Boot 有一個(gè)很棒的引擎,支持將你的 Spring Boot 應(yīng)用程序轉(zhuǎn)化為 GraalVM native images。

1 安裝

我正在使用一個(gè)出色的 Java 包管理器 SDKMAN。我還在運(yùn)行帶有 macOS 的 Apple Silicon 芯片。所以,這個(gè)事實(shí)和我喜歡并鼓勵(lì)使用 GraalVM 的事實(shí)稍后會(huì)有些重要,所以不要忘了。將會(huì)有測(cè)試!

sdk install java 22-graalce

我還會(huì)設(shè)置它為你的默認(rèn)選擇:

sdk default java 22-graalce

在繼續(xù)之前,打開(kāi)一個(gè)新的 shell,然后通過(guò)運(yùn)行 javac --versionjava --version,和 native-image --version 來(lái)驗(yàn)證一切是否正常。

如果你是在遙遠(yuǎn)的未來(lái)閱讀這篇文章的(我們已經(jīng)有飛行汽車(chē)了嗎?)而且有 50-graalce,那么就盡情安裝那個(gè)版本!版本越新越好!

2 你總得從某處開(kāi)始...

在這一點(diǎn)上,我想要開(kāi)始構(gòu)建了!所以,我去了互聯(lián)網(wǎng)上第二喜歡的地方,Spring Initializr - start.spring.io - 并生成了一個(gè)新的項(xiàng)目,使用以下規(guī)格:

  • 我選擇了 3.3.0-snapshot 版本的 Spring Boot。3.3 還沒(méi)有正式發(fā)行,但應(yīng)該在短短幾個(gè)月內(nèi)就會(huì)。與此同時(shí),不斷前進(jìn)!這個(gè)版本對(duì) Java 22 有更好的支持。
  • 我選擇了 Maven 作為構(gòu)建工具。
  • 我添加了 GraalVM Native Support 支持,H2 Database,和 JDBC API 支持。

我在我的 IDE 中打開(kāi)了項(xiàng)目,像這樣:idea pom.xml?,F(xiàn)在我需要配置一些 Maven 插件以支持 Java 22 和一些我們將在本文中看到的預(yù)覽功能。這是我的完整配置的 pom.xml。它有點(diǎn)密集,所以我會(huì)在代碼結(jié)束后來(lái)介紹一下。

COPY<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0-SNAPSHOT</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><properties><java.version>22</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.graalvm.sdk</groupId><artifactId>graal-sdk</artifactId><version>23.1.2</version></dependency><dependency><groupId>org.graalvm.nativeimage</groupId><artifactId>svm</artifactId><version>23.1.2</version><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.10.1</version><configuration><buildArgs><buildArg> --features=com.example.demo.DemoFeature</buildArg><buildArg> --enable-native-access=ALL-UNNAMED </buildArg><buildArg> -H:+ForeignAPISupport</buildArg><buildArg> -H:+UnlockExperimentalVMOptions</buildArg><buildArg> --enable-preview</buildArg></buildArgs></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><argLine>--enable-preview</argLine></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><enablePreview>true</enablePreview></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><compilerArguments> --enable-preview </compilerArguments><jvmArguments> --enable-preview</jvmArguments></configuration></plugin><plugin><groupId>io.spring.javaformat</groupId><artifactId>spring-javaformat-maven-plugin</artifactId><version>0.0.41</version><executions><execution><phase>validate</phase><inherited>true</inherited><goals><goal>validate</goal></goals></execution></executions></plugin></plugins></build><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository><repository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></pository></repositories><pluginRepositories><pluginRepository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></pluginRepository><pluginRepository><id>spring-snapshots</id><name>Spring Snapshots</name><url>https://repo.spring.io/snapshot</url><releases><enabled>false</enabled></releases></pluginRepository></pluginRepositories>
</project>

我知道,我知道!很多!但實(shí)際上并不是這樣。這個(gè) pom.xml 幾乎和我從 Spring Initializr 獲取的一模一樣。主要改變:

  • 重新定義 maven-surefire-pluginmaven-compiler-plugin 支持預(yù)覽功能。
  • 添加 spring-javaformat-maven-plugin 用來(lái)支持格式化我的源代碼。
  • 添加兩個(gè)新依賴(lài)項(xiàng):org.graalvm.sdk:graal-sdk:23.1.2org.graalvm.nativeimage:svm:23.1.2,都是專(zhuān)門(mén)為后面我們將需要的 GraalVM Feature 實(shí)現(xiàn)創(chuàng)建的
  • native-maven-pluginspring-boot-maven-plugin<configuration> 部分添加了配置節(jié)

非常快就到了,Spring Boot 3.3 將會(huì)正式發(fā)布并支持 Java 22,所以可能這個(gè)構(gòu)建文件的一半會(huì)消失。(真是春天的清理!)

3 編程快速說(shuō)明

LanguageDemonstrationRunner ,一個(gè)功能性接口,聲明可拋 Throwable

package com.example.demo;@FunctionalInterface
interface LanguageDemonstrationRunner {void run() throws Throwable;}

我還有一個(gè) ApplicationRunner,反過(guò)來(lái),它注入了我所有的功能接口實(shí)現(xiàn),然后調(diào)用它們的 run 方法,捕獲并處理 Throwable。

    // ...    @BeanApplicationRunner demo(Map<String, LanguageDemonstrationRunner> demos) {return _ -> demos.forEach((_, demo) -> {try {demo.run();} //catch (Throwable e) {throw new RuntimeException(e);}});}// ...

好的,既然我們已經(jīng)講過(guò)了,那就開(kāi)始吧!

4 再見(jiàn),JNI!

此版本終于等待了已久的 Project Panama 的發(fā)布。我最期待的三個(gè)特性之一,另外兩個(gè)特性是:

  • 虛擬線(xiàn)程
  • GraalVM native images

它們至少已經(jīng)成為現(xiàn)實(shí)六個(gè)月了。Project Panama 是讓我們能夠利用長(zhǎng)期以來(lái)被拒之門(mén)外的 C 和 C++ 代碼的星系?;叵肫饋?lái),如果它支持 ELF,我想象。例如 Rust 和 Go 程序可以編譯成與 C 兼容的二進(jìn)制文件,所以我想象(但沒(méi)有嘗試過(guò))這意味著與這些語(yǔ)言的互操作也足夠容易。在本節(jié)中,當(dāng)我提到“原生代碼”時(shí),我指的是以某種方式編譯的二進(jìn)制文件,它們可以像 C 庫(kù)那樣被調(diào)用。

從歷史上看,Java 一直是孤立的。對(duì)于 Java 開(kāi)發(fā)人員來(lái)說(shuō),重新使用原生 C 和 C++ 代碼并不容易。這是有道理的。原生、特定于操作系統(tǒng)的代碼只會(huì)破壞 Java 的“一次編寫(xiě),到處運(yùn)行”的承諾。它一直是有點(diǎn)禁忌的。但我不明白為什么會(huì)這樣。公平地說(shuō),盡管缺乏易用的原生代碼互操作功能,我們也做得不錯(cuò)。幾乎任何你想要做的事情,可能都有一個(gè)純 Java 解決方案存在,它可以在 Java 運(yùn)行的任何地方運(yùn)行。它運(yùn)行得很好,直到它不再運(yùn)行。Java 在這里錯(cuò)過(guò)了關(guān)鍵的機(jī)會(huì)。想象一下:

  • 如果 Kubernetes 是用 Java 構(gòu)建的?
  • 如果當(dāng)前的 AI 革命是由 Java 驅(qū)動(dòng)的?

這兩個(gè)概念會(huì)不可思議,當(dāng) Numpy、Scipy 和 Kubernetes 最初創(chuàng)建時(shí),但是今天?今天,他們發(fā)布了 Panama 項(xiàng)目。

Panama 項(xiàng)目引入了一種容易連接原生代碼的方法。支持兩個(gè)級(jí)別。你可以以相當(dāng)?shù)图?jí)的方式操縱內(nèi)存,并將數(shù)據(jù)在原生代碼中來(lái)回傳遞。我說(shuō)“來(lái)回”,但我可能應(yīng)該說(shuō)“向下和向上”到原生代碼。Panama 項(xiàng)目支持“向下調(diào)用”,即從 Java 調(diào)用原生代碼,以及“向上調(diào)用”,即從原生代碼調(diào)用 Java。你可以調(diào)用函數(shù)、分配和釋放內(nèi)存、讀取和更新 struct 中的字段等等。

讓我們來(lái)看一個(gè)簡(jiǎn)單的例子。代碼使用新的 java.lang.foreign.* API 查找一個(gè)叫做 printf 的符號(hào)(基本上就是 System.out.print()),分配內(nèi)存(有點(diǎn)像 malloc)緩沖區(qū),然后將該緩沖區(qū)傳遞給 printf 函數(shù)。

package com.example.demo;import org.springframework.stereotype.Component;import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.SymbolLookup;
import java.util.Objects;import static java.lang.foreign.ValueLayout.ADDRESS;
import static java.lang.foreign.ValueLayout.JAVA_INT;@Component
class ManualFfi implements LanguageDemonstrationRunner {// 這是包私有的,因?yàn)槲覀兩院髸?huì)需要它static final FunctionDescriptor PRINTF_FUNCTION_DESCRIPTOR =FunctionDescriptor.of(JAVA_INT, ADDRESS);private final SymbolLookup symbolLookup;// SymbolLookup 是 Panama API,但我有一個(gè)我正在注入的實(shí)現(xiàn)ManualFfi(SymbolLookup symbolLookup) {this.symbolLookup = symbolLookup;}@Overridepublic void run() throws Throwable {var symbolName = "printf";var nativeLinker = Linker.nativeLinker();var methodHandle = this.symbolLookup.find(symbolName).map(symbolSegment -> nativeLinker.downcallHandle(symbolSegment, PRINTF_FUNCTION_DESCRIPTOR)).orElse(null);try (var arena = Arena.ofConfined()) {var cString = arena.allocateFrom("hello, Panama!");Objects.requireNonNull(methodHandle).invoke(cString);}}}

這是我提出的 SymbolLookup 的定義。它是一種復(fù)合體,嘗試一個(gè) SymbolLookup,如果第一個(gè)失敗,則嘗試另一個(gè)。

@Bean
SymbolLookup symbolLookup() {var loaderLookup = SymbolLookup.loaderLookup();var stdlibLookup = Linker.nativeLinker().defaultLookup();return name -> loaderLookup.find(name).or(() -> stdlibLookup.find(name));
}

運(yùn)行這個(gè),你會(huì)看到它打印出 hello, Panama!.

您可能想知道為什么我沒(méi)有選擇更有趣的例子。事實(shí)證明,在所有os中你既能理所當(dāng)然地享有,在計(jì)算機(jī)上也能感知到自己做了些什么的東西幾乎沒(méi)有。IO 似乎是我能想到的所有東西,而且控制臺(tái) IO 更容易理解。

但 GraalVM 原生鏡像咋樣呢?它并不支持你可能想做的每件事。至少目前,它不在蘋(píng)果芯片運(yùn)行,只在 x86 芯片。我開(kāi)發(fā)了這個(gè)例子,并設(shè)置了 GitHub 操作在 x86 Linux 環(huán)境中查看結(jié)果。對(duì)于我們這些不使用英特爾芯片的 Mac 開(kāi)發(fā)者來(lái)說(shuō),這有點(diǎn)遺憾,但我們大多數(shù)人不是將產(chǎn)品部署到蘋(píng)果設(shè)備上,我們是部署到 Linux 和 x86 上,所以這不是一個(gè)破壞協(xié)議的事情。

還有一些其他限制。如GraalVM 原生映像僅支持我們復(fù)合中的第一個(gè) SymbolLookup, loaderLookup。如果那個(gè)不起作用,那么它們都將不起作用。

GraalVM 想要知道你在運(yùn)行時(shí)會(huì)做的一些動(dòng)態(tài)事情,包括外部函數(shù)調(diào)用。你需要提前告訴它。對(duì)于其他需要此類(lèi)信息的大多數(shù)事情,如反射、序列化、資源加載等,你需要編寫(xiě) .json 配置文件(或讓 Spring 的 AOT 引擎為你編寫(xiě))。這個(gè)特性是如此新,以至于你必須走下幾個(gè)抽象層次并編寫(xiě)一個(gè) GraalVM Feature 類(lèi)。Feature 有回調(diào)方法,在 GraalVM 的本地編譯生命周期中被調(diào)用。你將告訴 GraalVM 我們最終會(huì)在運(yùn)行時(shí)調(diào)用的原生函數(shù)的簽名,即形態(tài)。這是 Feature。只有一行價(jià)值。

package com.example.demo;import org.graalvm.nativeimage.hosted.Feature;
import org.graalvm.nativeimage.hosted.RuntimeForeignAccess;import static com.example.demo.ManualFfi.PRINTF_FUNCTION_DESCRIPTOR;public class DemoFeature implements Feature {@Overridepublic void duringSetup(DuringSetupAccess access) {// 這是唯一重要的一行。注意:我們正在分享// 我們稍早從 ManualFfi bean 中的 PRINTF_FUNCTION_DESCRIPTOR。RuntimeForeignAccess.registerForDowncall(PRINTF_FUNCTION_DESCRIPTOR);}}

然后我們需要連接所有的特性,通過(guò)將 --features 屬性傳遞給 GraalVM 原生圖像 Maven 插件配置來(lái)告知 GraalVM。我們還需要解鎖外部 API 支持和解鎖實(shí)驗(yàn)性事物。(我不知道為什么在 GraalVM 原生鏡像中這是實(shí)驗(yàn)性的,而在 Java 22 本身中它不再是實(shí)驗(yàn)性的)。還需要告訴 GraalVM 允許所有未命名類(lèi)型的原生訪(fǎng)問(wèn)。所以,總的來(lái)說(shuō),這是最終的 Maven 插件配置。

<plugin><groupId>org.graalvm.buildtools</groupId><artifactId>native-maven-plugin</artifactId><version>0.10.1</version><configuration><buildArgs><buildArg>--features=com.example.demo.DemoFeature</buildArg><buildArg>--enable-native-access=ALL-UNNAMED</buildArg><buildArg>-H:+ForeignAPISupport</buildArg><buildArg>-H:+UnlockExperimentalVMOptions</buildArg><buildArg>--enable-preview</buildArg></buildArgs></configuration>
</plugin>

這是一個(gè)了不起的結(jié)果。我將這個(gè)示例中的代碼編譯成一個(gè)在 GitHub Actions 運(yùn)行中的 GraalVM 原生圖像然后執(zhí)行它。應(yīng)用程式,我提醒您 - 具有 Spring JDBC 支持、完整和嵌入式 SQL 99 兼容的 Java 數(shù)據(jù)庫(kù)叫做 H2,以及類(lèi)路徑上的所有內(nèi)容 - 在 0.031 秒(31 毫秒,或 31 千分之一秒)內(nèi)執(zhí)行,占用數(shù)十兆字節(jié)的 RAM,并從 GraalVM 原生鏡像調(diào)用原生 C 代碼!

我真的很高興,大家。我已經(jīng)等這一天很久了。

但這確實(shí)感覺(jué)有點(diǎn)低級(jí)。歸根到底,你在使用一個(gè) Java API 來(lái)以編程方式創(chuàng)建和維護(hù)原生代碼中的結(jié)構(gòu)。這有點(diǎn)像使用 JDBC 中的 SQL。JDBC 允許你在 Java 中操縱 SQL 數(shù)據(jù)庫(kù)記錄,但你不是在 Java 中編寫(xiě) SQL 并在 Java 中編譯它并在 SQL 中執(zhí)行它。存在一個(gè)抽象增量;你將字符串發(fā)送到 SQL 引擎,然后以 ResultSet 對(duì)象的形式獲取回來(lái)的記錄。Panama 中的低級(jí) API 也是如此。它起作用,但你沒(méi)有調(diào)用原生代碼,你正在查找符號(hào)和操縱內(nèi)存。

所以,他們發(fā)布了一個(gè)與之分離但相關(guān)的工具叫做 jextract。你可以指向一個(gè) C 頭文件,如 stdio.hprintf 函數(shù)定義在其中,它會(huì)生成模仿底層 C 代碼調(diào)用簽名的 Java 代碼。我沒(méi)有在這個(gè)示例中使用它,因?yàn)樯傻?Java 代碼最終與底層平臺(tái)綁定。我指它去 stdio.h 并獲得了很多 macOS 特定的定義。我可以隱藏所有這些在運(yùn)行時(shí)檢查操作系統(tǒng)的后面,然后動(dòng)態(tài)加載特定的實(shí)現(xiàn),但是,嗯,這篇博客已經(jīng)太長(zhǎng)了。如果你想看怎么運(yùn)行 jextract,這是我用的可以在 macOS 和 Linux 上工作的 bash 腳本。你的里程可能會(huì)有所不同。

#!/usr/bin/env bash
LINUX=https://download.java.net/java/early_access/jextract/22/3/openjdk-22-jextract+3-13_linux-x64_bin.tar.gz
MACOS=https://download.java.net/java/early_access/jextract/22/3/openjdk-22-jextract+3-13_macos-x64_bin.tar.gzOS=$(uname)DL=""
STDIO=""if [ "$OS" = "Darwin" ]; thenDL="$MACOS"STDIO=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/stdio.h
elif [ "$OS" = "Linux" ]; thenDL=$LINUXSTDIO=/usr/include/stdio.h
elseecho "Are you running on Windows? This might work inside the Windows Subsystem for Linux, but I haven't tried it yet.."
fiLOCAL_TGZ=tmp/jextract.tgz
REMOTE_TGZ=$DL
JEXTRACT_HOME=jextract-22mkdir -p "$(dirname  $LOCAL_TGZ )"
wget -O $LOCAL_TGZ $REMOTE_TGZ
tar -zxf "$LOCAL_TGZ" -C .
export PATH=$PATH:$JEXTRACT_HOME/binjextract  --output src/main/java  -t com.example.stdio $STDIO

想想看,我們擁有簡(jiǎn)單的外部函數(shù)互操作性、提供驚人擴(kuò)展性的虛擬線(xiàn)程,以及靜態(tài)鏈接的、快如閃電、內(nèi)存高效、自足的 GraalVM 原生圖像二進(jìn)制文件。再次告訴我,為何你要開(kāi)始一個(gè)新的 Go 項(xiàng)目?:-)

5 勇敢的新世界

Java 22 是一個(gè)驚人的新版本。它帶來(lái)了一系列巨大的功能和提升生活品質(zhì)的改進(jìn)。記住,不可能總是這樣美好!沒(méi)有人能每六個(gè)月就一貫地推出改變游戲規(guī)則的新功能。這是不可能的。所以,我們不妨心存感激,盡情享受目前吧,好嗎? :) 在我看來(lái),上一個(gè)版本 Java 21,或許是我見(jiàn)過(guò)的自 Java 5 以來(lái)最重要的一次發(fā)布,甚至可能是最早。這可能是最大的一次!

那里有許多特性值得你關(guān)注,包括:

  • 數(shù)據(jù)導(dǎo)向編程
  • 虛擬線(xiàn)程

六月前為支持那次發(fā)布所做的博客中,覆蓋這些及更多內(nèi)容,Hello, Java 21

6 虛擬線(xiàn)程、結(jié)構(gòu)化并發(fā)和作用域值

虛擬線(xiàn)程是真正重要的部分。閱讀我剛才鏈接給你的博客,往下翻。 (不要像 the Primeagen 那樣,他讀了文章但在還沒(méi)讀到最佳部分 - 虛擬線(xiàn)程之前就走神了!我的朋友……為什么??)

如果你正在運(yùn)行 I/O 綁定的服務(wù),虛擬線(xiàn)程是提高你的云基礎(chǔ)設(shè)施花費(fèi)、硬件等的一個(gè)方法。它們使得你可以將現(xiàn)有的針對(duì) java.io 中的阻塞 I/O API 編寫(xiě)的代碼轉(zhuǎn)換為虛擬線(xiàn)程,并處理更好的規(guī)模化。通常的效果是,你的系統(tǒng)不再不斷地等待線(xiàn)程的可用性,從而平均響應(yīng)時(shí)間下降,更好的是,你會(huì)發(fā)現(xiàn)系統(tǒng)能夠同時(shí)處理更多的請(qǐng)求!我無(wú)法強(qiáng)調(diào)它的重要性。虛擬線(xiàn)程是棒極了!如果你在使用 Spring Boot 3.2,你只需要指定 spring.threads.virtual.enabled=true 即可享受它們!

虛擬線(xiàn)程是旨在使 Java 成為我們都知道它應(yīng)該得到的精簡(jiǎn)、高效的規(guī)?;瘷C(jī)器的一系列新功能的一部分,而且它正在起作用!虛擬線(xiàn)程是三個(gè)旨在協(xié)同工作的功能中的唯一一個(gè)已經(jīng)在發(fā)布形式中交付的功能。

結(jié)構(gòu)化并發(fā)和作用域值都還沒(méi)有落地。結(jié)構(gòu)化并發(fā)為構(gòu)建并發(fā)代碼提供了一個(gè)更優(yōu)雅的編程模型,而作用域值則提供了一個(gè)效率更高、更通用的 ThreadLocal<T> 替代方案,特別適用于虛擬線(xiàn)程的背景下,其中你現(xiàn)在可以實(shí)際擁有數(shù)百萬(wàn)個(gè)線(xiàn)程。想象一下對(duì)于每一個(gè)這樣的線(xiàn)程都有重復(fù)的數(shù)據(jù)!

這些功能在 Java 22 中處于預(yù)覽階段。我不知道它們現(xiàn)在是否值得展示。在我心中,虛擬線(xiàn)程是魔法的一部分,它們之所以如此神奇,正是因?yàn)槟阏娴牟恍枰私馑鼈?#xff01;只設(shè)置那一個(gè)屬性,你就可以啟動(dòng)了。

虛擬線(xiàn)程為你提供了類(lèi)似 Python、Rust、C#、TypeScript、JavaScript 的 async/await 或 Kotlin 中的 suspend 之類(lèi)的驚人規(guī)模,而無(wú)需使用那些語(yǔ)言功能所需的固有冗長(zhǎng)代碼和繁瑣工作。這是少數(shù)幾次,除了可能是 Go 的實(shí)現(xiàn),Java 在結(jié)果上是直接更勝一籌的時(shí)候。Go 的實(shí)現(xiàn)是理想的,但那只是因?yàn)樗麄冊(cè)?1.0 版本中就內(nèi)置了這一點(diǎn)。事實(shí)上,Java 的實(shí)現(xiàn)更為杰出,精確地說(shuō)是因?yàn)樗c較老的平臺(tái)線(xiàn)程模型共存。

7 隱式聲明的類(lèi)和實(shí)例主方法

這個(gè)預(yù)覽功能是巨大的生活質(zhì)量提升,盡管結(jié)果代碼更小,而我非常歡迎它。不幸的是,它目前還與 Spring Boot 不兼容?;靖拍钍?#xff0c;總有一天你將能夠只有一個(gè)頂層 main 方法,而不需要今天 Java 中的所有儀式。作為應(yīng)用程序的入口點(diǎn),這不是很好嗎?沒(méi)有 class 定義,沒(méi)有 public static void,沒(méi)有不必要的 String[] 參數(shù)。

void main() {System.out.println("Hello, world!");
}

8 超類(lèi)之前的語(yǔ)句

這是一個(gè)不錯(cuò)的生活質(zhì)量功能?;旧?#xff0c;Java 不允許你在子類(lèi)中調(diào)用 super 構(gòu)造函數(shù)之前訪(fǎng)問(wèn) this。其目的是為了避免與無(wú)效狀態(tài)相關(guān)的一類(lèi)錯(cuò)誤。但這有點(diǎn)過(guò)于嚴(yán)厲,并迫使開(kāi)發(fā)者在想要在調(diào)用 super 方法之前進(jìn)行任何非平凡計(jì)算時(shí),不得不轉(zhuǎn)而使用 private static 輔助方法。這是有時(shí)所需的體操動(dòng)作的一個(gè)例子。我從 the JEP 頁(yè)面偷來(lái)了這個(gè)例子:

class Sub extends Super {Sub(Certificate certificate) {super(prepareByteArray(certificate));}// 輔助方法private static byte[] prepareByteArray(Certificate certificate) {var publicKey = certificate.getPublicKey();if (publicKey == null)throw new IllegalArgumentException("null certificate");return switch (publicKey) {case RSAKey rsaKey -> ///...case DSAPublicKey dsaKey -> ...//...default -> //...};}}

你可以看到問(wèn)題。這個(gè)新的 JEP,目前還是預(yù)覽功能,將允許你將該方法直接內(nèi)聯(lián)在構(gòu)造函數(shù)本身,增強(qiáng)可讀性并消除代碼冗余。

9 未命名的變量和模式

未命名的變量和模式是另一個(gè)提升生活質(zhì)量的功能。然而,它已經(jīng)交付了。

當(dāng)你在創(chuàng)建線(xiàn)程,或者使用 Java 8 的流和收集器時(shí),你將創(chuàng)建很多 lambda。實(shí)際上,在 Spring 中有很多情況下你會(huì)使用 lambdas。只需考慮所有的 *Template 對(duì)象,及其以回調(diào)為中心的方法。 JdbcClientRowMapper<T> 也跳入腦海!

有趣的事實(shí):Lambda 首次在 2014 年的 Java 8 版本中介紹。 (是的,已經(jīng)過(guò)去了一個(gè)十年!那時(shí)人們?cè)谧霰疤魬?zhàn),世界癡迷于自拍棒、FrozenFlappy Bird。),但它們的驚人品質(zhì)是幾乎前 20 年的 Java 代碼在一夜之間如果方法期望單個(gè)方法接口實(shí)現(xiàn)就可以參與 lambdas。

Lambdas 是驚人的。它們?cè)?Java 語(yǔ)言中引入了一個(gè)新的重用單元。最棒的部分是它們被設(shè)計(jì)為以某種方式嫁接到運(yùn)行時(shí)的現(xiàn)有規(guī)則上,包括自動(dòng)將所謂的功能接口或 SAMs(單抽象方法)接口適應(yīng)到 lambdas。我唯一的抱怨是,屬于包含作用域的 lambda 中引用的東西必須設(shè)置為 final。這個(gè)問(wèn)題已經(jīng)修復(fù)?,F(xiàn)在必須拼出每個(gè) lambda 參數(shù),即使我根本沒(méi)打算使用它,現(xiàn)在,有了 Java 22,那也得到修復(fù)了!這里是一個(gè)冗長(zhǎng)的例子,僅為了展示兩處 _ 字符的使用。因?yàn)槲铱梢浴?/p>

package com.example.demo;import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Component;import javax.sql.DataSource;@Component
class AnonymousLambdaParameters implements LanguageDemonstrationRunner {private final JdbcClient db;AnonymousLambdaParameters(DataSource db) {this.db = JdbcClient.create(db);}record Customer(Integer id, String name) {}@Overridepublic void run() throws Throwable {var allCustomers = this.db.sql("select * from customer ")// 這里! .query((rs, _) -> new Customer(rs.getInt("id"), rs.getString("name"))).list();System.out.println("all: " + allCustomers);}}

該類(lèi)使用 Spring 的 JdbcClient 查詢(xún)底層數(shù)據(jù)庫(kù)。它一頁(yè)一頁(yè)地翻閱結(jié)果,然后涉及我們的 lambda,它符合 RowMapper<Customer> 類(lèi)型,以幫助我們將結(jié)果適應(yīng)到與我的領(lǐng)域模型一致的記錄。 RowMapper<T> 接口,我們的 lambda 符合它,有一個(gè)方法 T mapRow(ResultSet rs, int rowNum) throws SQLException,期望兩個(gè)參數(shù):我將需要的 ResultSet,以及我?guī)缀醪恍枰?rowNum。現(xiàn)在,多虧 Java 22,我不需要指定它。就像在 Kotlin 或 TypeScript 中一樣,只需插入 _ 即可。不錯(cuò)!

10 聚集者

Gatherers 是另一個(gè)在預(yù)覽中也很好的功能。 Viktor Klang,他在 Akka 上的了不起工作以及他在 Lightbend 期間對(duì) Scala futures 的貢獻(xiàn)。如今,他是 Oracle 的一名 Java 語(yǔ)言架構(gòu)師,他一直在研究的就是新的 Gatherer API。順便說(shuō)一下,Stream API 也是在 Java 8 中引入的,這 - 順便說(shuō)一下 - 給了 Java 開(kāi)發(fā)者一個(gè)機(jī)會(huì),與 lambdas 一起,大大簡(jiǎn)化和現(xiàn)代化他們現(xiàn)有的代碼,并向更多函數(shù)式編程方向發(fā)展。

它構(gòu)建了一個(gè)在值的流上進(jìn)行一系列轉(zhuǎn)換的模型。然而,這個(gè)抽象模型并不盡完美。Streams API 提供了大量便利的方法,這些方法能夠滿(mǎn)足 99% 的使用場(chǎng)景,但當(dāng)你遇到找不到合適方法的情況時(shí),通常會(huì)感到挫敗,因?yàn)橹安](méi)有一種簡(jiǎn)易的方式可以直接擴(kuò)展新的操作。在過(guò)去十年間,關(guān)于為 Streams API 引入新操作的提案數(shù)不勝數(shù),甚至在最初的 lambda 表達(dá)式提案中,也有討論和妥協(xié),目的是讓編程模型有足夠的靈活性來(lái)支持新操作的加入?,F(xiàn)在,這一目標(biāo)作為一個(gè)預(yù)覽性質(zhì)的功能終于實(shí)現(xiàn)了。Gatherers 提供了一個(gè)稍微更底層的抽象層次,使你能夠在不需要將 Stream 具體化為 Collection 的情況下,在 Streams 上引入多種新操作。以下是一個(gè)我毫不掩飾地直接從 Viktor 和他的團(tuán)隊(duì)那里取得的示例。

package com.example.demo;import org.springframework.stereotype.Component;import java.util.Locale;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Gatherer;
import java.util.stream.Stream;@Component
class Gatherers implements LanguageDemonstrationRunner {private static <T, R> Gatherer<T, ?, R> scan(Supplier<R> initial,BiFunction<? super R, ? super T, ? extends R> scanner) {class State {R current = initial.get();}return Gatherer.<T, State, R>ofSequential(State::new,Gatherer.Integrator.ofGreedy((state, element, downstream) -> {state.current = scanner.apply(state.current, element);return downstream.push(state.current);}));}@Overridepublic void run() {var listOfNumberStrings = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).gather(scan(() -> "", (string, number) -> string + number).andThen(java.util.stream.Gatherers.mapConcurrent(10, s -> s.toUpperCase(Locale.ROOT)))).toList();System.out.println(listOfNumberStrings);}}

該段代碼的重點(diǎn)在于,這里描述了一個(gè)名為 scan 的方法,它返回一個(gè) Gatherer<T,?,R> 類(lèi)型的實(shí)現(xiàn)。每個(gè) Gatherer<T,O,R> 對(duì)象都需要一個(gè)初始化函數(shù)和一個(gè)整合函數(shù)。雖然這種實(shí)現(xiàn)自帶默認(rèn)的合并函數(shù)和完成函數(shù),但你也可以自行覆蓋它們。它通過(guò)讀取所有的數(shù)字條目,并為每一個(gè)條目逐步構(gòu)造一個(gè)字符串,字符串隨著數(shù)字的增加不斷累積。結(jié)果就像這樣:先是 1,然后是 12,接著是 123,直到 1234 等等。 上述例子還展示了 gatherers 是可以組合使用的。在這里,我們實(shí)際上操作了兩個(gè) Gatherer 對(duì)象:一個(gè)用于執(zhí)行掃描過(guò)程,另一個(gè)則把每個(gè)元素轉(zhuǎn)成大寫(xiě),并且這一轉(zhuǎn)換是并發(fā)進(jìn)行的。 如果您還沒(méi)能完全理解,沒(méi)關(guān)系,對(duì)于大多數(shù)人而言,這部分內(nèi)容可能會(huì)有些深?yuàn)W。大多數(shù)人可能無(wú)需自己編寫(xiě) Gatherers。但是,如果你想挑戰(zhàn)一下,也是可以試試的。我的朋友 Gunnar Morling 就在前幾天完成了這樣的工作。Gatherers 方法的巧妙之處在于,它使社區(qū)能夠根據(jù)自己的需求去設(shè)計(jì)解決方案。我很好奇這對(duì)于 Eclipse Collections、Apache Commons Collections 或者 Guava 這樣的著名項(xiàng)目會(huì)帶來(lái)什么影響?它們是否會(huì)推出 Gatherers?還有其他什么項(xiàng)目會(huì)加入這一趨勢(shì)?我期待看到很多實(shí)用的 gatherers 能夠聚集到同一個(gè)地方。

11 Class Parsing API

又一個(gè)令人期待的預(yù)覽性特性,這是 JDK 新增的部分,非常適合框架和基礎(chǔ)架構(gòu)開(kāi)發(fā)人員。它可以解答例如如何構(gòu)建 .class 文件和如何讀取 .class 文件的問(wèn)題。目前市場(chǎng)上有很多好用但不兼容,總是稍微有點(diǎn)落后的工具,比如 ASM(這個(gè)領(lǐng)域里的重量級(jí)解決方案),ByteBuddy,CGLIB 等。JDK 本身在其代碼庫(kù)中就包含了三種此類(lèi)解決方案!這類(lèi)庫(kù)在整個(gè)行業(yè)中隨處可見(jiàn),并且對(duì)于像 Spring 這樣的框架的開(kāi)發(fā)來(lái)說(shuō)至關(guān)重要,Spring 動(dòng)態(tài)地在運(yùn)行時(shí)創(chuàng)建類(lèi)來(lái)支持業(yè)務(wù)邏輯。你可以將它看作是一個(gè)反射 API,但它作用于 .class 文件——硬盤(pán)上實(shí)際的字節(jié)碼,而不是加載進(jìn) JVM 的對(duì)象。 這是一個(gè)簡(jiǎn)單的例子,展示了如何把一個(gè) .class 文件加載進(jìn)一個(gè) byte[] 數(shù)組,并對(duì)其進(jìn)行分析。

package com.example.demo;import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
import org.springframework.context.annotation.ImportRuntimeHints;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;import java.lang.classfile.ClassFile;
import java.lang.classfile.FieldModel;
import java.lang.classfile.MethodModel;@Component
@ImportRuntimeHints(ClassParsing.Hints.class)
class ClassParsing implements LanguageDemonstrationRunner {static class Hints implements RuntimeHintsRegistrar {@Overridepublic void registerHints(RuntimeHints hints, ClassLoader classLoader) {hints.resources().registerResource(DEFAULT_CUSTOMER_SERVICE_CLASS);}}private final byte[] classFileBytes;private static final Resource DEFAULT_CUSTOMER_SERVICE_CLASS = new ClassPathResource("/simpleclassfile/DefaultCustomerService.class");ClassParsing() throws Exception {this.classFileBytes = DEFAULT_CUSTOMER_SERVICE_CLASS.getContentAsByteArray();}@Overridepublic void run() {// this is the important logicvar classModel = ClassFile.of().parse(this.classFileBytes);for (var classElement : classModel) {switch (classElement) {case MethodModel mm -> System.out.printf("Method %s%n", mm.methodName().stringValue());case FieldModel fm -> System.out.printf("Field %s%n", fm.fieldName().stringValue());default -> {// ... }}}}}

這個(gè)例子稍微復(fù)雜一些,因?yàn)樗婕暗搅诉\(yùn)行時(shí)讀取資源。為了應(yīng)對(duì)這個(gè)過(guò)程,我實(shí)現(xiàn)了一個(gè)名為 Spring AOT RuntimeHintsRegistrar 的組件,它能生成一個(gè) .json 文件。這個(gè) JSON 文件記錄著我正在讀取的資源信息,比如具體來(lái)說(shuō)就是 DefaultCustomerService.class 文件的數(shù)據(jù)。不過(guò),這些都是幕后的技術(shù)細(xì)節(jié),主要是為了在 GraalVM 上進(jìn)行本地鏡像編譯的時(shí)候使用。 而代碼底部的部分則頗有意思,我們對(duì) ClassElement 實(shí)例進(jìn)行了枚舉,并通過(guò)模式匹配的方法一一提取了各個(gè)要素。這真是太棒了!

12 String Templates

又一項(xiàng)預(yù)覽特性的加入,String templates 為 Java 帶來(lái)了字符串插值功能!Java 中的多行字符串(String)已經(jīng)使用了一段時(shí)間。這個(gè)新功能允許開(kāi)發(fā)者將編譯后字符串中可見(jiàn)的變量直接嵌入到字符串值里面。最精彩的部分?從理論上講,這個(gè)機(jī)制還可以自定義!不滿(mǎn)意現(xiàn)有的語(yǔ)法?你完全可以創(chuàng)造一個(gè)屬于你自己的版本。

package com.example.demo;import org.springframework.stereotype.Component;@Component
class StringTemplates implements LanguageDemonstrationRunner {@Overridepublic void run() throws Throwable {var name = "josh";System.out.println(STR.""" name: \{name.toUpperCase()}""");}}

13 總結(jié)

作為一名 Java 和 Spring 開(kāi)發(fā)者,現(xiàn)在是一個(gè)前所未有的好時(shí)機(jī)!我一直強(qiáng)調(diào)這一點(diǎn)。我們仿佛獲得了一個(gè)嶄新的語(yǔ)言和運(yùn)行時(shí)環(huán)境,這一進(jìn)步 - 奇妙地 - 保持了對(duì)歷史版本的兼容。這是我目睹 Java 社區(qū)所開(kāi)展的最具雄心壯志的軟件項(xiàng)目之一,我們很幸運(yùn)能夠見(jiàn)證其成果的誕生。從現(xiàn)在起,我打算將 Java 22 和支持 Java 22 的 GraalVM 用于我的所有開(kāi)發(fā)工作,我希望您也能跟我一起 關(guān)注我,緊跟本系列專(zhuān)欄文章,咱們下篇再續(xù)!

作者簡(jiǎn)介:魔都技術(shù)專(zhuān)家兼架構(gòu),多家大廠(chǎng)后端一線(xiàn)研發(fā)經(jīng)驗(yàn),各大技術(shù)社區(qū)頭部專(zhuān)家博主。具有豐富的引領(lǐng)團(tuán)隊(duì)經(jīng)驗(yàn),深厚業(yè)務(wù)架構(gòu)和解決方案的積累。

負(fù)責(zé):

  • 中央/分銷(xiāo)預(yù)訂系統(tǒng)性能優(yōu)化

  • 活動(dòng)&優(yōu)惠券等營(yíng)銷(xiāo)中臺(tái)建設(shè)

  • 交易平臺(tái)及數(shù)據(jù)中臺(tái)等架構(gòu)和開(kāi)發(fā)設(shè)計(jì)

  • 車(chē)聯(lián)網(wǎng)核心平臺(tái)-物聯(lián)網(wǎng)連接平臺(tái)、大數(shù)據(jù)平臺(tái)架構(gòu)設(shè)計(jì)及優(yōu)化

    目前主攻降低軟件復(fù)雜性設(shè)計(jì)、構(gòu)建高可用系統(tǒng)方向。

參考:

  • 編程嚴(yán)選網(wǎng)

本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布!

http://www.risenshineclean.com/news/44633.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)常規(guī)自適應(yīng)信息流廣告優(yōu)化師
  • 網(wǎng)站建設(shè)中的html頁(yè)面seo網(wǎng)站優(yōu)化培訓(xùn)
  • 2018年網(wǎng)站建設(shè)做搜索引擎推廣多少錢(qián)
  • 網(wǎng)站建站客戶(hù)需求表單鄭州網(wǎng)站制作選擇樂(lè)云seo
  • 做網(wǎng)站最主要是什么招聘seo專(zhuān)員
  • 建設(shè)銀行澳洲招聘網(wǎng)站最新足球消息
  • 禪城網(wǎng)站建設(shè)報(bào)價(jià)it培訓(xùn)課程
  • wordpress文件的完整url地址seo是什么意思啊
  • 響應(yīng)式網(wǎng)站的制作網(wǎng)站制作百度大數(shù)據(jù)查詢(xún)平臺(tái)
  • 貴陽(yáng)網(wǎng)站推廣網(wǎng)絡(luò)營(yíng)銷(xiāo)策劃推廣方案
  • cad培訓(xùn)班一般學(xué)費(fèi)多少深圳網(wǎng)站設(shè)計(jì)專(zhuān)家樂(lè)云seo
  • c語(yǔ)言除了做網(wǎng)站還能干什么廣州疫情升級(jí)
  • 網(wǎng)站建設(shè)公司六安網(wǎng)站seo方案
  • 龍巖網(wǎng)站建設(shè)全包sem和seo是什么職業(yè)
  • 中企動(dòng)力做過(guò)的網(wǎng)站女教師遭網(wǎng)課入侵視頻
  • wordpress獲取當(dāng)前目錄父目錄id吉林seo管理平臺(tái)
  • 縣文化館網(wǎng)站建設(shè)方案市場(chǎng)調(diào)研報(bào)告1000字
  • 哪些網(wǎng)站做ip向小說(shuō)神秘網(wǎng)站
  • 央視新聞seo的五個(gè)步驟
  • 尋找徐州網(wǎng)站開(kāi)發(fā)企業(yè)網(wǎng)絡(luò)營(yíng)銷(xiāo)青島
  • 深圳廣告公司前十強(qiáng)seo簡(jiǎn)單速排名軟件
  • 單頁(yè)網(wǎng)站在線(xiàn)制作公司搜索seo
  • 做網(wǎng)站上哪買(mǎi)空間鄭州seo顧問(wèn)外包公司
  • 書(shū)畫(huà)網(wǎng)站模板下載跨境電商seo什么意思
  • 網(wǎng)絡(luò)營(yíng)銷(xiāo)的方法包括哪些重慶seo是什么
  • wordpress 子主題路由seo沒(méi)什么作用了
  • 素材網(wǎng)站源碼成品視頻直播軟件推薦哪個(gè)好一點(diǎn)
  • 如何仿造一個(gè)網(wǎng)站做廣州網(wǎng)絡(luò)廣告推廣公司
  • 企業(yè)網(wǎng)站 手機(jī)網(wǎng)站 app 微網(wǎng)站廣州網(wǎng)站建設(shè)系統(tǒng)
  • wordpress is_mobile上海關(guān)鍵詞排名優(yōu)化公司