【jdk】jdk11 jdk17 jdk21 springboot3 的新特性 虚拟线程创建方式

前言:按照博主的个人理解,一般来说 除了jdk8时代 说jdk8的新特性是特指jdk8这一个版本的特性,之后例如jdk11 jdk17新特性 都是泛特性
什么意思呢? 比如jdk11新特性,一般是指jdk9——jdk11 这一个泛版本的所有新特性,就jdk9引入的 List.of Map.of等api 我们也统称是jdk11的新特性

为什么大家只提及这几个版本

为什么我们很少听到jdk9,jdk10…等其它版本呢
个人认为被大家广为流传的版本需要同时满足以下两点:

  1. 有重大更新的版本 比如典型的jdk8时代带来的lambda等特性
  2. 是LTS版本 (长期支持版本) 作为企业 肯定也需要考虑这点

jdk11主要新特性

这里说的是泛特性 即jdk9——jdk11
主要例举博主接触到的,应该也是我们比较常见的一些情况

  1. 新增了List.of , Map.of 等api,简化了代码 (jdk9特性)
    (List.of()类似Arrays.asList , 都是不可删除的list)

  2. stream流api更新
    在旧版本的jdk中,stream流有个致命的缺点 不能break! 这使得我们在需要break的时候及其不方便, 有了takeWhile方法 可以一定程度上实现break。

   	    List<Integer> list = Stream.of(4, 2 ,3).takeWhile(i->(i<3)).toList();
        // 输出空list
        System.out.println(list);

        List<Integer> list1 = Stream.of(1, 2 ,3).takeWhile(i->(i<3)).toList();
        // 输出 [1,2]
        System.out.println(list1);

但是注意!它是按顺序来执行的,如果第一个元素都不符合 就直接break了
我们可以举个例子

List<String> nameList = List.of("小帅","孟秋与你","小丑");
// break写法:
for(String name : nameList){
  if("孟秋与你".equals(name)){
  	// 返回一个新的数组
  	return List.of(name);
	break;
   }
}

//  但是如果用takeWhile 将会返回空数组!
// 因为第一个元素"小帅"就不符合我们的判断条件 直接退出了
  1. jdk部分模块被移除 需要单独引入

     例如javaFx被移除 (主要是桌面开发相关的api)
     jaxb涉及的也被移除 (这个主要是xml相关的api)
     rmi 相关的包也被移除 
     (这个日常开发基本用不到 ,对我们来说主要是学习如何防止被rmi远端执行 
     例如著名的log4j事件 黑客就是通过rmi执行的)
     其它模块的移除...
    
  2. 默认垃圾收集器的变化
    说的就是G1 gc收集器

  3. 接口里面支持private方法
    这个可以视为jdk8新增default 方法的一个补充,比如default方法过于庞大,这个时候就可能需要一个private方法抽取逻辑了。

public interface Test{
   
    default void test() {
    	// do other
        testHandle();
    }

    private void testHandle() {
    // do other
    }
}
  1. 语法的简单变化
    这个基本就是泛型加一个类型减一个类型的事了,具体情况不记得了,之前遇过一次,不过影响不大 遇到的话 启动代码的时候如果报错就知道了,非常容易判断并修改的

jdk17主要新特性

tips :
如果idea选择不了高版本的jdk 说明idea版本太低了
比如idea2021选不了jdk17, idea2023.1选不了jdk21
对我们大部分人来说 会同时涉及springboot、jdk、idea的升级

同样指的是泛特性 jdk12——jdk17

  1. NPE优化提示
    这个可以说非常友好了, 在链式调用时 会准确提示NPE的位置
    在这里插入图片描述
    旧版jdk (此处指 jdk<= 11) 的提示:
    在这里插入图片描述

  2. 文本块
    这个在编写长文本的时候非常有用
    旧:

   return "<html>\n" +
        " <body>\n" +
        " <p>csdn: 孟秋与你</p>\n" +
        " </body>\n" +
        "</html>";

新:

    return """
        <html>
            <body>
                <p>csdn: 孟秋与你</p>
            </body>
        </html>
        """;
  1. stream流Api进一步更新
    可以直接使用 toList()方法了,不需要使用collect(Collectors.toList())这么麻烦
        List<Integer> list = Stream.of(4, 2 ,3).takeWhile(i->(i<3)).toList();
  1. switch优化
    旧写法 每个分支都要写break 及其臃肿
 public String test() {

        String res = "";
        switch (1){
            case 1:
                res="打工";
                break;
            // ....

            case 6:
                res="休息";
                break;
            default:
                res = "打工";
                break;
        }
        return res;
    }

新写法:
(注意语法 箭头指向的内容即表明了返回值 所以是在return的时候使用该写法)

    public String test() {

       return switch (1) {
            case 1 ->"上班";

            case 6 -> "休息";

           default -> "上班";
       };
      
    }
  1. sealed、permits关键字

    虽然这是jdk17的新特性,但是博主是在jdk21虚拟线程相关的源码中才看到的,这两个关键字主要是用来限制继承关系的,相当于给继承加了个枚举限制,用个例子来解释就特别容易理解


/**
 * sealed + permits 配合使用: 
 * 表示Animal类只可以被 Cat 和 Dog类继承
 * Cat类 和 Dog类需要声明为final (否则可能被多重继承)
 * 若Cat和Dog类没声明为final 或其它类继承了Animal 会报编译时错误
 */
 
public sealed class Animal permits Cat,Dog {
}

public final class Cat extends Animal{
}

public final class Dog extends Animal{
}

// 如果People继承Animal 则People类和Animal类都会直接提示错误
public class People extends Animal{
}

博主是在以下源码看到的这个用法,jdk虚拟线程相关类:BaseVirtualThread (需要jdk21)
在这里插入图片描述

jdk21主要新特性

在这里插入图片描述
上面是官方文档提及的,博主简单概述一下:

虚拟线程

  1. 虚拟线程
    这个是最大的新特性了,将操作系统的线程 提到了jvm层面管理,线程开销极大的缩减了,要说怎么理解这个虚拟线程,博主个人把它当做一个操作系统线程的缓存池来理解,智者见智。

    当然,稍微追踪一下源码很容易发现 它实际原理是通过forkJoinPool来实现的。
    (在jdk8引入的completablefuture 默认也是forkJoinPool来实现的)。

      Runnable runnable = () -> {
            System.out.println("Hello, 孟秋与你");
        };

        // 方式一:使用静态构建器方法 启动,一个快速的虚拟线程
        Thread.startVirtualThread(runnable);

        // 方式二:builder 方式启动
        Thread.Builder.OfVirtual virtual = Thread.ofVirtual();
        // 可以自定义些属性
        virtual.name("virtual thread");
        virtual.start(runnable);

        // 方式三:Executors 也支持了虚拟线程
        ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
        executorService.execute(runnable);

        // 为了确保主线程不会过早退出,等待一段时间
        try {
            Thread.sleep(1111111000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


虚拟线程有没有必要使用线程池 ?
我们知道阿里规范是不允许通过Executors来创建线程的,虚拟线程它成本低 自动销毁 无需复用,但是线程池也有拒绝策略之类的功能存在,硬要用 好像也不是不行 。
总之显得很矛盾,博主个人观点是不要使用线程池。

如果硬用池化,手动创建方式例子如下:

        ThreadFactory virtualThreadFactory = Thread.ofVirtual().factory();

        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                4,
                4,
                60L,
                TimeUnit.SECONDS,
                // 注: 这个是无界队列
                new LinkedBlockingQueue<>(),
                virtualThreadFactory
        );
        
		  Runnable runnable1 = () -> {
		            System.out.println("Hello, 孟秋与你1111111");
		            try {
		                Thread.sleep(3000L);
		            } catch (InterruptedException e) {
		                throw new RuntimeException(e);
		            }
		        };
		        
	        for (int i = 0; i < 100; i++) {
	            executor.execute(runnable1);
	        }

核心就是线程工厂要设置成虚拟线程工厂,其它参数都是一样的

我们可以看一下源码
在这里插入图片描述

  1. 新的字符串方法
    引入了一些新的字符串方法,进一步增强了字符串操作的能力,如字符串格式化和更高效的字符串比较​

  2. Sequenced Collections
    JDK 21增加了有序集合(Sequenced Collections)的支持,这是一个新的集合类型,元素有固定的遇见顺序,并且提供了一组统一的操作。新的接口包括SequencedCollection、SequencedSet和SequencedMap​ ​。

  3. ZGC垃圾收集器

  4. record 增强
    现在基本都用lomhok了 博主没去看这个

  5. 模式匹配增强(Pattern Matching Enhancements)
    模式匹配得到了进一步增强,特别是在switch语句中的应用。这使得代码更加简洁和表达力更强​ 。

  6. 性能、安全的优化,方法的弃用之类的优化

springboot3新特性

  1. 因为springboot3强制伴随着jdk的升级,所以首先至少需要掌握jdk17的特性
    (见上文jdk17主要新特性章节)

  2. SPI机制的调整
    这是一个比较重大的调整,如果不了解这个变动,可能导致项目直接就无法启动了。

    旧版本中 SPI机制是通过spring.factories文件来注册bean的,在springboot3.0中 正式放弃了这一特性 。

    (在springboot2.7中,作为一个过渡阶段,这两种配置方式都生效 但spring.factories其实已经不再被推荐了)

springboot <= 2.7 文件springboot >=3.0 文件
META-INF/spring.factoriesMETA-INF/spring/org.springframework.boot.autoconfigure.Autoconfiguration.imports

配置写法也有所调整,新配置直接换行即可:
在这里插入图片描述

在idea 2024.1中,新的配置方式 bean会报红线,但不必担心,我们debug的时候可以看到 bean是成功注册了的。
(在idea中使用jdk21 需要下载idea2024)
在这里插入图片描述

  1. 伴随着security的升级 涉及部分api调整,见官方文档
https://docs.spring.io/spring-security/reference/5.8/migration/index.html
  1. 其它特性见github官方文档
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide
  1. bootstrap.yml被弃用
    这个不是springboot3的新特性,在springboot 2.4以后就废弃了,鉴于可能有项目直接从springboot2.3升级到springboot3,这里也顺带提一下。

springboot3、jdk版本、idea版本的对应关系

jdk版本springboot版本idea版本
173.0.0> idea2022
213.3.1idea2024

首先springboot3.0是强制要使用jdk17的,不能使用jdk11和jdk8;

但是在springboot3.0 不能使用jdk21 会报错:Failed to read candidate component class
(因为有springboot3.0的时候 jdk21还没诞生)

如果想使用jdk21的话,需要将springboot升级至较新的springboot3.3.1版本

  • 14
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孟秋与你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值