JDK19新功能

1.1 记录模式 (预览)

如果不经常关注JDK更新的朋友肯定对记录模式很陌生,甚至都没听过,其实记录模式非常好用。官方的解释是这样的:“记录模式由一个类型、一个可能为空的记录组件模式列表(用于匹配相应的记录组件)和一个可选标识符组成,带有标识符的记录模式称为命名记录模式,变量称为记录模式变量。“
对于新手来说,不加以白话文的解释是看不懂的。我们直接上代码,用代码给大家作解释:

record Test(int a, int b) {}

形如以上代码的就是记录模式。
record是一种新类型,本质上是一个final类,在修改所有属性的同时加final,会自动编译public get hashcode、equals、toString方法,这样减少了代码量。record在Java 14中被提出,在Java 15中进入预览阶段,并在Java 16中发布。
我们编写一个Drone类,定义sn、brand、name:

package com.wljslmz;

public record Drone(String sn, String brand, String name) {
}

record的使用:

package com.wljslmz;
public class RecordTest {
    public static void main(String[] args) {
        Drone drone1 = new Drone("0a9f55785ebc4c52", "DJI", "M30无人机");
        Drone drone2 = new Drone("7400f6c1c5644c6e", "DJI", "精灵4无人机");
        System.out.println(drone1);
        System.out.println(drone2);
    }
}

输出结果:

Drone[sn=0a9f55785ebc4c52, brand=DJI, name=M30无人机]
Drone[sn=field 7400f6c1c5644c6e, brand=DJI, name=精灵4无人机]

在Java 19中,模式匹配被引入record中,这样的话就可以使用instanceof:

package com.wljslmz;

public class RecordTest {

    public static void main(String[] args) {
        Drone drone1 = new Drone("0a9f55785ebc4c52", "DJI", "M30无人机");
        if(drone1 instanceof Drone droneType){
            System.out.println(drone1.sn());
         }
         
         Drone drone2 = new Drone("7400f6c1c5644c6e", "DJI", "精灵4无人机");
        if(drone2 instanceof Drone(String sn, String brand, String name)){
            System.out.println("无人机2的序列号为:"+sn+",厂商为:"+brand+",名称为:"+name);
         }
    }
}

输出结果:

0a9f55785ebc4c52
无人机2的序列号为:7400f6c1c5644c6e,厂商为:DJI,名称为:精灵4无人机

1.2 虚拟线程(预览)

在讲虚拟线程前,给大家稍微普及一下线程的知识。

研究过Java虚拟机的朋友都知道,线程一直是Java并发编程中非常重要的一部分。Thread是Java中的并发单元,每个Thread线程都提供了一个栈来存储局部变量和方法调用,以及关于线程上下文的信息。Java线程和系统内核线程是一一对应的,Java线程是由系统内核线程调度的,所以到并发场景中,我们第一个想到的是增加线程数目去提高系统的性能。
在这里插入图片描述
多线程模型
多线程模型能不能解决并发中绝大多数问题?

答案肯定是:能!但是可取吗?

小型的并发场景可取,但是并发数很大的场景就不可取了。线程的数目当然是越多,越能提高系统的性能,但是这个带来的直接后果就是成本增加,上面我们说过了,Java的线程是由系统内核直接调用的,那么也就意味着,多线程需要在物理上增加机器,试想一下,这种成本代价得多高?

那有人肯定说了,不是还有线程池吗?

不错,线程池确实能提高并发场景下系统的性能,但是,请注意,线程池只是帮助你如何更好的管理线程、利用线程,本身不会凭空给你创造出线程来,最终工作的还是底层的内核线程。而且线程池往往会受限于CPU、网络、内存等,所以从硬件的角度来看,并没有解决实际问题。

因此,Java19引入了虚拟线程。

我们来看下虚拟线程的模型是什么样的:
在这里插入图片描述
多线程模型中的线程在虚拟线程模型中被称为平台线程,一个平台线程对应多个虚拟线程,最终其实也是由内核线程去驱动。

在体验上虚拟线程与Threads没有区别,并且兼容之前的API,但相比而言它们占用的资源非常少,并且优化了硬件使用效率。

package com.wljslmz.demo;import Java.util.concurrent.ExecutorService;
import Java.util.stream.IntStream;import static Java.util.concurrent.Executors.*;/*** @author: wangrui* @date: 2022/10/18 15:12* @description: 虚拟线程测试*/
public class VirtualThreadTest {
	public static void main(String[] args) {
		long start = System.currentTimeMillis();
		try (ExecutorService executor = newVirtualThreadPerTaskExecutor()) {
			IntStream.range(0, 1000000).forEach(index -> {executor.submit(() -> {
					Thread.sleep(1000);
					return index;
				});
			});
			System.out.println("执行消耗时间:" + (System.currentTimeMillis() - start) + "毫秒");
		}
	}
}

执行结果:

执行消耗时间:8550毫秒

代码中我们创建了100万个线程,每个线程睡眠1秒钟,完成这个操作最终只花了8秒多,假如我们使用的是普通线程去处理或者线程池去处理,那么这个速度能差异到多少呢?

我们稍微改动一下代码:

long start = System.currentTimeMillis();
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 1000000; i++) {
	executor.submit(() -> {
		try {Thread.sleep(1000);
		}catch (InterruptedException e) {
			e.printStackTrace();
		}
	});
}
System.out.println("执行消耗时间:" + (System.currentTimeMillis() - start) + "毫秒");

最后执行的时间:

执行消耗时间:13459毫秒

差距是不是也不是很大,确实是的,因为虚拟线程只会增加程序的吞吐量,不会增加程序的处理速度。

1.3 Vector API

Vector API最初在Java 16中被引入,Java 19带来了它的第四次迭代。简单来说Vector API可以加速矢量计算,在数学计算领域非常有用。
在传统计算中,数据的处理都是一个一个处理的,这种操作被称为“SISD”,即“单指令,单数据”:
在这里插入图片描述
但是在Vector API中,数据的计算可以做到“单指令,多数据”,即“SIMD”:

在这里插入图片描述
这个代表什么意思呢?

比如我们对两组数据进行处理,普通处理的方式就是,遍历这些数组,然后逐个处理:

int[] array1 = {1, 2, 3, 4, 5};
int[] array2 = {6, 7, 8, 9, 10};
int[] array3 = new int[5];
for (int i = 0; i < 5; i++) {
	array3[i] = array1[i] + array2[i];
}
System.out.println(Arrays.toString(array3));

如上代码,我们定义了两个数组,现在我们想对相同下标的数进行相加,所以我们遍历了数组,一对一对进行处理,最终的结果就是:

[7, 9, 11, 13, 15]

如果使用Vector API应该怎么写?

int[] array1 = {1, 2, 3, 4, 5};
int[] array2 = {6, 7, 8, 9, 10};
int[] array3 = new int[5];
VectorSpecies<Integer> intvector = IntVector.SPECIES_PREFERRED;
int[] intvectorBound = intvector.loopBound(5);
int i = 0;
for (; i < intvectorBound; i += intvector.length()) {
	var array1Intvector = IntVector.fromArray(intvector, array1, i);
	var array2Intvector = IntVector.fromArray(intvector, array2, i);
	var array3Intvector = array1Intvector.add(array2Intvector);array3Intvector.intoArray(array3, i);
}
for (; i < 5; i++) {
	array3[i] = array1[i] + array2[i];
}
System.out.println(Arrays.toString(array3));

这个代码看起来是比非Vector API复杂了,但是处理的思想完全不一样,普通处理方法是单个数据单个数据进行处理,而Vector API是多组数据处理,两者如果在大数据量计算的时候,其性能就可想而知了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值