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

前言:按照博主的个人理解,一般来说 除了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。

java 复制代码
   	    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了

我们可以举个例子

java 复制代码
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方法抽取逻辑了。

java 复制代码
public interface Test{
   
    default void test() {
    	// do other
        testHandle();
    }

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

jdk17主要新特性

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

  1. NPE优化提示

    这个可以说非常友好了, 在链式调用时 会准确提示NPE的位置

    旧版jdk (此处指 jdk<= 11) 的提示:

  2. 文本块

    这个在编写长文本的时候非常有用

    旧:

java 复制代码
   return "<html>\n" +
        " <body>\n" +
        " <p>csdn: 孟秋与你</p>\n" +
        " </body>\n" +
        "</html>";

新:

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

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

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

新写法:

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

java 复制代码
    public String test() {

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

            case 6 -> "休息";

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

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

java 复制代码
/**
 * 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来实现的)。

java 复制代码
      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来创建线程的,虚拟线程它成本低 自动销毁 无需复用,但是线程池也有拒绝策略之类的功能存在,硬要用 好像也不是不行 。

总之显得很矛盾,博主个人观点是不要使用线程池。

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

java 复制代码
        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. 性能、安全的优化,方法的弃用之类的优化

相关推荐
游王子31 分钟前
Springboot与xxl-job
java·spring boot·后端
秋刀prince38 分钟前
【JD-GUI】MacOS 中使用Java反编译工具JD-GUI
java·macos·策略模式
青云交1 小时前
Java面试题--JVM大厂篇之G1 GC的分区管理方式如何减少应用线程的影响
java·垃圾回收器(gc)的性能·区域划分(region)·并行和并发回收·区域优先回收·可预测的停顿时间·jvm算法
codefly-xtl1 小时前
探索 Java 8 中的 Stream API
java
Jack_hrx2 小时前
在 Java 中从 for 循环中移出元素的原理及解决方案
java·循环·for循环·数组下标越界
科学的发展-只不过是读大自然写的代码2 小时前
qt 读写json格式的文件应用举例 工具函数
java·qt·json
qq17239350582 小时前
学习java第一百一十六天
java·开发语言·学习
FM_南风2 小时前
java定时任务实现
java·开发语言
csdncjh2 小时前
spring boot初始化的几个总结
java·spring boot
G皮T2 小时前
【Spring Boot】Java 持久层 API:JPA
java·spring boot·hibernate·jpa·spring data