JDK21发布了!面试官:来,谈下jdk21的新特性!

1.前言

JDK21 计划23年9月19日正式发布,尽管一直以来都是“版随意出,换 8 算我输”,但这么多年这么多版本的折腾,若是之前的 LTS 版本JDK17你还觉得不错,那 JDK21还是有必要关注一下,因为会有一批重要更新发布到生产环境中,特别是被众人期待已久的虚拟线程,纵然说这东西我感觉没有必要的用不到,需要的早已转go了,但作为近几年JDK一个“重要”的更新,在实际开发应用中还是有相当的价值。如果说之前的 JDK17你还觉得没必要折腾,那 JDK21确实有必要关注一下了。因为 JDK21 引入了一种新型的并发编程模式。当前 Java 中的多线程并发编程绝对是另我们都非常头疼的一部分,感觉就是学起来难啃,用起来难用。但是转头看看使用其他语言的朋友们,根本就没有这个烦恼嘛,比如 GoLang,感觉人家用起来就很丝滑因此这篇文章主要摘录了这次更新中个人觉得相对有价值的几点做个基本的介绍,想要体验新功能的同学可以阅读一下。

2.JDK21主要特型

2.1 结构化并发

结构化并发是一种编程范式,旨在通过提供结构化和易于遵循的方法来简化并发编程。使用结构化并发,开发人员可以创建更容易理解和调试的并发代码,并且不容易出现竞争条件和其他与并发有关的错误。在结构化并发中,所有并发代码都被结构化为称为任务的定义良好的工作单元。任务以结构化方式创建、执行和完成,任务的执行总是保证在其父任务完成之前完成。

Structured Concurrency(结构化并发)可以让多线程编程更加简单和可靠。在传统的多线程编程中,线程的启动、执行和结束是由开发者手动管理的,因此容易出现线程泄露、死锁和异常处理不当等问题。

使用结构化并发,开发者可以更加自然地组织并发任务,使得任务之间的依赖关系更加清晰,代码逻辑更加简洁。结构化并发还提供了一些异常处理机制,可以更好地管理并发任务中的异常,避免因为异常而导致程序崩溃或数据不一致的情况。

除此之外,结构化并发还可以通过限制并发任务的数量和优先级,防止资源竞争和饥饿等问题的发生。这些特性使得开发者能够更加方便地实现高效、可靠的并发程序,而无需过多关注底层的线程管理。

2.2 作用域值

作用域值是JDK 20中引入的一项功能,它允许开发人员创建受限于特定线程或任务的值。与线程本地变量类似,作用域值可以与虚拟线程和结构化并发一起使用。通过作用域值,开发人员可以以结构化的方式在任务和虚拟线程之间传递值,而无需复杂的同步或锁定机制。这种特性非常适用于在应用程序的不同部分之间传递上下文信息,如用户身份验证或请求特定数据。使用作用域值,我们可以更加优雅地处理并发编程,并提高代码的可读性和维护性。

2.3 禁止动态加载代理

在运行时动态加载代理时发出警告。这些警告是为了未来的版本做准备,以默认禁止动态加载代理以提高系统完整性。为了平衡下面两点

  • 可维护性(对运行代码进行特殊修改的能力)
  • 完整性(假设运行代码不会被任意更改)

同时,还确保大多数不需要动态加载代理的工具不受影响。另外,该计划要求保持动态加载代理的能力与“超能力”功能(如深度反射)的一致性。代理是一种组件,可以在应用程序运行时更改应用程序代码。这个概念最初在2004年JDK 5的Java平台分析架构中引入,作为一种让工具(特别是分析器)检测类的方法。尽管代理最初被设计用于良性检测,但高级开发人员发现它有一些用例,比如面向切面编程可以以任意方式改变应用程序行为。同样,代理也可以改变JDK本身等代码。因此,JDK 5要求在命令行中指定代理,以确保应用程序所有者批准使用代理。在JDK 21中,计划要求像启动时加载代理一样,需要应用程序所有者批准动态加载代理。这个变化将进一步提高Java平台的默认系统完整性。

2.4 密钥封装机制API

  • RSA密钥封装机制(RSA-KEM)

  • 椭圆曲线集成加密方案(ECIES)等KEM算法

  • 美国国家标准与技术研究院(NIST)后量子密码学标准化过程的候选算法

另一个目标是能在更高级别的协议(如传输层安全协议TLS)和密码方案(如混合公钥加密HPKE)中使用KEM。安全提供者可以用Java或本机代码实现KEM算法,并包含RFC 9180中定义的Diffie-Hellman KEM(DHKEM)的实现。

2.5 弃用Windows 32位x86端口

提案的目标是在未来的版本中移除特定端口。我们计划更新构建系统,以便在尝试为Windows 32位x86配置构建时发出错误消息。当然,你可以通过新的配置选项来屏蔽这些错误消息。另外,我们还计划将该端口及其相关功能标记为已弃用,并删除相关文档。这样做的原因是,我们注意到最后一个支持32位操作的Windows操作系统——Windows 10将于2025年10月结束生命周期。

2.6 匿名类和实例main方法预览

旨在使Java语言进化,以便学生在无需理解面向大型程序设计的语言特性的情况下编写第一个Java程序。学生可以为单类程序编写简化的声明,然后无缝地扩展程序以使用更高级的特性,而不是使用Java的单独方言。该提案不仅可以为Java提供平稳的入门,而且可以减少编写简单Java程序(如脚本和命令行实用程序)的麻烦。

2.7 无名模式和变量的预览

未命名模式匹配记录组件,而不声明组件的名称或类型,未命名变量可以初始化但不使用。两者都用下划线字符_表示。该提案旨在通过省略不必要的嵌套模式来改善记录模式的可读性,并通过识别必须声明但不会使用的变量来改善所有代码的可维护性。

2.8 Generational ZGC(分代式 ZGC)

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

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将成为默认设置。

旨在通过为年轻对象和旧对象维护独立的代来改善应用程序性能。年轻对象往往很快就会死亡;维护独立的代将允许ZGC更频繁地收集年轻对象。运行在分代ZGC上的应用程序应会看到以下好处:分配中断风险更低,需要的堆内存开销更低,垃圾收集CPU开销更低。这些好处应该可以在吞吐量不明显下降的情况下实现。

2.9 Record Patterns (记录模式)

这个更新主要简化了类型判断与赋值的使用,类型判断后无需显式强制转换且如果模式匹配,变量被初始化为要匹配的模板值, 这个说起来比较拗口,结合代码大家理解下,我感觉还是挺有用的,这里我把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);
    }
}

记录模式和类型模式可以嵌套,以启用强大的、声明性的和可组合的数据导航和处理形式。该提案的目标包括扩展模式匹配以解构记录类的实例,添加嵌套模式以启用更可组合的数据查询。此特性与switch表达式和语句的模式匹配(见下文)共同演化。当前的JEP将在继续的经验和反馈的基础上通过进一步完善来最终确定该特性。除了少量编辑变化外,主要变化是删除了记录模式在增强的for语句标题中出现的支持。该特性可能会在未来的JEP中重新提出。

2.10 Pattern Matching for switch (switch模式匹配)

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

使得switch表达式或语句可以针对许多模式进行测试,每个模式都有特定的操作,这样复杂的数据查询可以安全简洁地表达。

该特性最初在JDK 17中提出,之后在JDK 18、JDK 19和JDK 20中进行了完善。它将在JDK 21中通过进一步的优化最终确定。与前面的JEP相比,主要变化是删除了带括号的模式并允许合格的enum常量,如带switch表达式和语句的常量。目标包括通过允许模式出现在case标签中来扩展switch表达式和语句的表达能力和适用范围,允许switch的历史 null敌意在需要时得到放松,并通过要求模式switch语句覆盖所有潜在的输入值来增加switch语句的安全性。另一个目标是确保现有的switch表达式和语句继续编译而不变,并具有相同的语义。

2.11 向量API的第六个孵化器

该API表达了在支持的CPU体系结构上可靠编译为优化向量指令的向量计算,其性能优于等效的标量计算。向量API此前在JDK 16至JDK 20中进行了孵化。这个最新版本包括性能增强和错误修复。该提案的目标包括清晰简洁,与平台无关,并在x64和AArch64体系结构上提供可靠的运行时编译和性能。其他目标包括在向量计算无法完全表示为向量指令序列时优雅降级。

2.12 外部函数和内存API的第三次预览

使得Java程序能够与Java运行时之外的代码和数据进行互操作。它通过高效调用外部函数和安全访问外部内存,使得Java程序能够调用本机库并处理本机数据,而无需使用JNI(Java本机接口)带来的脆弱性和危险性。这个API之前在JDK 20和JDK 19中进行了预览。JDK 21预览中的改进包括增强布局路径,以解引用地址布局,并引入新的元素;集中管理Arena接口中本地段生命周期;提供备用的本机链接器实现以及删除VaList。该提案旨在提高易用性、性能、通用性和安全性。它的目标不是重新实现JNI,也不会对JNI进行任何改变。

2.13 虚拟线程

先看下官方对虚拟线程(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.

A 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中的线程是基于操作系统线程的平台线程,按照1:1的模式调度,这导致线程的创建和执行都非常耗资源,并且受系统限制。而现在的虚拟线程则是由JDK提供,可以将其视为在平台线程基础上创建的一批线程,它们有效地共享所属的平台线程即操作系统线程的资源,从而提高系统利用率,并且没有数量限制。

目标描述:

1、使采用简单的按请求开启线程方式编写的服务器应用程序能够以接近最佳的硬件利用率进行扩展。

可以每个请求开启一个虚拟线程,实现简单直接的同时可以最大程度地提升硬件利用率;

2、使使用java.lang.Thread API的现有代码能够以最小的改动采用虚拟线程。

之前的多线程实现代码可以在很小的修改下迁移到虚拟线程;

3、使用现有JDK工具方便地进行虚拟线程的故障排除、调试和分析。

使用现有JDK工具可以轻松地对虚拟线程进行故障排除、调试和分析;

简而言之,现在我们可以轻松地创建一个轻量级的虚拟线程,实现简单性,同时充分发挥硬件性能。

以下是一个简单的示例代码:

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

轻量级线程,它承诺大大减少编写、维护和观察高吞吐量并发应用程序的工作量。该计划的目标包括使按线程请求风格编写的服务器应用程序能够在接近最佳硬件利用率的情况下扩展,使使用lang.Thread API的现有代码通过最小更改采用虚拟线程,并使用当前JDK工具轻松调试和分析虚拟线程。虚拟线程在JDK 20和JDK 19中进行了预览,将在JDK 21中最终确定。在JDK 21中,虚拟线程现在始终支持线程本地变量,并使创建不具有这些变量的虚拟线程成为不可能。保证对线程本地变量的支持可以确保更多现有库可以不变地与虚拟线程一起使用,并帮助将面向任务的代码迁移到使用虚拟线程。

2.14 序列集合SequencedCollection Interface(顺序集合 接口)

兄弟们,作为一个天天CRUD,CPU跑不满20%的程序员, 相比上面的虚拟线程,这次关于集合类接口的更新我感觉更实在一些

JDK21中我们常用的Set、List、Deque与Map集合类分别继承实现了SequencedCollection、 SequencedMap 接口,为我们执行一些顺序性操作比如获取头尾值提供了各类接口方法

继承关系如下图所示:

img
img

接口定义如下

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

2.15 字符串模板

JDK 21中的预览功能,它通过将字面文本与嵌入式表达式和处理器结合来补充Java的现有字符串文本块,以产生特定结果。这种语言特性和API旨在通过使动态计算的值易于表示字符串来简化Java程序的编写。它有望增强表达式的可读性,提高程序安全性,保持灵活性,并简化使用以非Java语言编写的字符串的API。启用从字面文本和嵌入式表达式组合派生非字符串表达式的开发也是一个目标。

与这些JDK增强提案分开,据Oracle的Java团队称,JDK 21将更改JDK在Windows上为网络接口分配名称的方式。执行网络多播或使用java.net.NetworkInterface API的应用程序维护人员应注意此更改。

JDK历史上为Windows上的网络接口合成名称。这已更改为使用Windows操作系统分配的名称。此更改可能会影响使用NetworkInterface.GetbyName(String name)方法查找网络接口的代码。JDK 21还将在JDK飞行记录器中进行关键更改,包括使从命令行分析飞行记录更加容易。

总结

以上是我认为JDK21版本中一些有价值的更新的总结。如果你希望进一步了解,请自行查看官网https://openjdk.org/projects/jdk/21/,并在发布后进行实际验证。

近年来Java受到其他各种语言的冲击,给人一种跌落神坛的感觉。因此,我想看看这次的更新是否能给Java带来一些活力。当前Java语言的下降趋势也可以说是国内IT行业兴衰起伏的一个缩影。当然,作为一个提供生产力的编程语言,整个建立在Java周边的完整、稳定、强大的生态系统仍然在适当领域发挥着重要作用,这是短时间内无法改变的。但如果你指望靠它干到退休,恐怕连那些收了你学费的培训机构也不敢这样承诺。程序员的职业寿命从来不是某种编程语言决定的。

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/178134.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华清远见嵌入式学习——C++——作业一

作业要求&#xff1a; 代码&#xff1a; #include <iostream>using namespace std;int main() {string str;cout << "请输入一个字符串&#xff1a;" << endl;getline(cin,str);int dx0,xx0,sz0,kg0,qt0;int len str.size() 1;for(int i0;i<l…

HarmonyOS 传感器开发指南

HarmonyOS 系统传感器是应用访问底层硬件传感器的一种设备抽象概念。开发者根据传感器提供的Sensor接口&#xff0c;可以查询设备上的传感器&#xff0c;订阅传感器数据&#xff0c;并根据传感器数据定制相应的算法开发各类应用&#xff0c;比如指南针、运动健康、游戏等。 运作…

Centos 如何判断分区是mbr还是gpt格式

1 介绍 MBR 自20世纪80年代初以来的标准分区表格式每个驱动器最多支持四个主分区最多可以划分2TB的磁盘 GPT GPT是MBR分区表格式的后续每个驱动器最多支持128个分区可以将一个磁盘分区到最大到18艾字节 对小于2TB的磁盘使用MBR对大于2TB的磁盘使用GTP 2 查询方式 2.1 fdis…

校园虚拟化部署与横向扩展统一存储

项目背景 这所隶属教育部直属重点大学&#xff0c;学校设有11个学科体系&#xff0c;现有本硕博学生共29000余人&#xff0c;为积极响应“中国教育现代化2023战略部署”&#xff0c;校方制定教育信息化2.0发展目标&#xff0c;通过平台融合&#xff0c;数据驱动、技术赋能等措…

Linux常见指令基础知识

目录 初始Linux操作系统 Linux背景&#xff1a; 开源 &#xff1a; 发行版本&#xff1a; ​编辑 OS概念&#xff0c;定位&#xff1a; 使用 XShell 远程登录 Linux Linux相关知识 文件是什么&#xff1f; 路径分隔符 &#xff08;.&#xff09; 和 &#xff08;. .&…

Docker Swarm总结+Jenkins安装配置与集成(5/5)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

反射、枚举以及lambda表达式

1. 反射 1.1 定义 java的.class文件在运行时会被编译为一个Class对象&#xff0c;既然是对象&#xff0c;那么我们就可以通过一定的方式取到这个对象&#xff0c;然后对于这个对象进行一系列操作&#xff08;改变原本类的属性、方法&#xff09;。 这个操作就是反射&#xf…

数据仓库建模下篇

在实际业务中&#xff0c;给了我们一堆数据&#xff0c;我们怎么拿这些数据进行数仓建设呢&#xff0c;数仓工具箱作者根据自身多年的实际业务经验&#xff0c;给我们总结了如下四步。 数仓工具箱中的维度建模四步走&#xff1a; 维度建模四步走 这四步是环环相扣&#xff0c…

JOSEF 可调漏电继电器 RT-L1KS φ25mm 导轨或面板安装

RT-L系列可调漏电继电器&#xff08;以下简称继电器&#xff09;适用于交流电压至690V&#xff0c;频率为50Hz&#xff0c;电流至1500A及以下漏电继电器中性点接地电路中。 RT-L系列可调型漏电继电器 RT-L1K可调型漏电继电器 RT-L2K可调型漏电继电器 RT-L3K可调型漏电继电器…

Mybaits-plus的使用

MybatisPlus特性 润物无声&#xff1a; 只做增强不做改变&#xff0c;引入它不会对现有工程产生改变&#xff0c;如丝般顺滑。 效率至上 只需简单配置&#xff0c;即可快速进行单表CRUD操作&#xff0c;从而节省大量时间。 使用MybatisPlus依赖基本步骤 引入MybatisPlus依…

echarts点击事件

有这么个需求要点击叶片的时候跳转页面 代码&#xff1a;点击之后 报错了 解决办法 1、使用箭头函数&#xff08;箭头函数没有自己的 this&#xff0c;所以在箭头函数中使用 this 时&#xff0c;其指向与外层作用域相同。&#xff09;或者使用闭包来解决上下文的问题。 2、使…

微信可以添加多少好友?

不知道有没有小伙伴好奇&#xff0c;微信到底可以添加多少好友&#xff1f;正好这个话题也上热搜了&#xff0c;我们就来了解一下。 有网友表示&#xff0c;自己的微信好友数量有10004个&#xff0c;已经不能再添加新的微信好友了。 一个微信号&#xff0c;可以添加的好友上限…

初识Linux(2).妈妈再也不用担心我Linux找不到门了。

文章目录 前言 1.man指令&#xff08;重要&#xff09;&#xff1a;例如&#xff1a; 2.cp指令&#xff08;重要&#xff09;&#xff1a;例如&#xff1a;把123.txt复制到a目录中类似window如下操作&#xff1a; 3.mv例如&#xff1a;类似window如下操作&#xff1a; 4.nano例…

算法效率的度量

算法效率的度量通常是通过时间复杂度和空间复杂度来描述的。 一、时间复杂度 算法中所有语句的执行次数之和为T(n)&#xff0c;它是算法问题规模n的函数&#xff0c;时间复杂度主要分析T(n)的数量级。 分类 1. 最好时间复杂度&#xff1a;最好情况下&#xff0c;算法的时间…

山西临县“5·7”火灾事故调查报告公布,揭秘富维烟火报警系统

近日&#xff0c;山西临县“57”火灾事故调查报告震惊全国&#xff0c;提醒我们火灾防控的重要性。在这起悲剧中&#xff0c;我们深刻认识到&#xff0c;及时发现火灾并迅速应对至关重要。这不仅是对生命安全的保护&#xff0c;也是对财产损失的有效减少。而在这方面&#xff0…

sCrypt 现已支持各类主流前端框架

sCrypt 现已支持各类主流前端框架&#xff0c;包括&#xff1a; ReactNext.jsAngularSvelteVue 3.x or 2.x bundled with Vite or Webpack 通过在这些支持的前端框架中集成sCrypt开发环境&#xff0c;你可以直接在前端项目里访问合约实例和调用合约&#xff0c;方便用户使用Se…

UE5 - 虚幻引擎各模块流程图

来自虚幻官方的一些资料&#xff0c;分享一下&#xff1b; 一些模块的流程图&#xff0c;比如动画模块&#xff1a; 或角色相关流程&#xff1a; 由于图片比较大&#xff0c;上传到了网络&#xff0c;可自取&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1BQ2KiuP08c…

【JavaScript】alert的使用方法 | 超详细

alert作用效果 alert&#xff08;&#xff09;方法用于显示带有一条指定消息和一个确认的按钮的警告框。 alert使用方法 方法一&#xff1a;直接写在script标签内 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"&…

Docker Swarm总结+基础、集群搭建维护、安全以及集群容灾(1/5)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

线上异步任务突然不能回写100%

项目场景&#xff1a; 需求是一个作业&#xff0c;需要运行一组sql&#xff0c;所有sql运行完成&#xff0c;更新作业进度为100%&#xff0c;状态为完成。sql需要是在大数据平台&#xff0c;通过yarn调度&#xff0c;异步执行。 kafka监听每个sql的执行状态&#xff0c;所有sql…