Flink--API 之 Source 使用解析

目录

一、Flink Data Sources 分类概览

(一)预定义 Source

(二)自定义 Source

二、代码实战演示

(一)预定义 Source 示例

基于本地集合

基于本地文件

基于网络套接字(socketTextStream)

(二)自定义 Source 示例

三、Kafka Source 应用

四、总结


        在大数据处理领域,Apache Flink 作为一款强大的流式计算框架,既能应对流处理场景,也可处理批处理任务。而数据来源(Data Sources)作为整个计算流程的 “源头活水”,其多样性与合理运用至关重要。本文将深入剖析 Flink 中 Data Sources 的相关知识,并结合丰富代码示例,助力大家透彻理解与灵活运用。

一、Flink Data Sources 分类概览

Flink 在批 / 流处理中常见的 source 主要分为两大类:预定义 Source 和自定义 Source。

(一)预定义 Source

基于本地集合的 source(Collection-based-source)

        通过env.fromElements()可传入可变参数创建 DataStream,支持如 Tuple、自定义对象等复合形式,但要注意类型需一致,不一致时虽可用Object接收但使用易报错,像env.fromElements("haha", 1)这种就会有问题;env.fromCollection()支持多种Collection具体类型(如ListSetQueue)来构建 DataStream;env.fromSequence()可基于开始和结束值创建 DataStream(曾有env.generateSequence()方法创建基于 Sequence 的 DataStream,不过现已废弃),此类方式常应用于学习测试编造数据场景。

基于文件的 source(File-based-source)

        能读取本地文件与 HDFS 路径文件,如env.readTextFile("datas/wc.txt")可读取本地datas目录下wc.txt文件,env.readTextFile("hdfs://bigdata01:9820/home/a.txt")能获取 HDFS 特定路径文件数据。操作时要留意相对路径转绝对路径问题,避免因路径差错引发异常。

基于网络套接字(socketTextStream)

        socketTextStream(String hostname, int port)方法从指定 Socket 读取数据创建 DataStream,其为非并行 Source,有重载方法可指定行分隔符和最大重新连接次数,默认行分隔符是\n,最大重新连接次数为 0。使用前需先启动 Socket 服务(Mac 或 Linux 可在命令行终端输入nc -lk 8888,Windows 需安装netcat命令后操作),且该方式获取的 DataStream 并行度固定为 1。

(二)自定义 Source

SourceFunction

        非并行数据源(并行度只能 = 1),作为接口定义基础数据源规范,实现run方法持续产生数据,cancel方法用于停止数据源。

RichSourceFunction

        多功能非并行数据源(并行度只能 = 1),是类形式,相比SourceFunction,额外功能体现在实例化时有open方法执行一次(多并行度会多次执行,因多实例)、销毁实例时close方法执行一次,且能通过getRuntimeContext获取当前Runtime对象(底层 API)。

ParallelSourceFunction

        并行数据源(并行度能够 >= 1),接口形式,允许创建并行处理的数据源,例如自定义类实现此接口,按设定并行度生成数据。

RichParallelSourceFunction

        多功能并行数据源(并行度能够 >= 1),类形式且功能齐全,建议使用。继承它并重写相关方法,能充分利用并行特性高效产生数据,同时享有Rich类的openclose等方法优势。

二、代码实战演示

(一)预定义 Source 示例

在flink最常见的创建DataStream方式有四种: 

l 使用env.fromElements(),这种方式也支持Tuple,自定义对象等复合形式。
注意:类型要一致,不一致可以用Object接收,但是使用会报错,比如:env.fromElements("haha", 1);

源码注释中有写:


l 使用env.fromCollection(),这种方式支持多种Collection的具体类型,如List,Set,Queue
l 使用env.generateSequence()方法创建基于Sequence的DataStream --已经废弃了
l 使用env.fromSequence()方法创建基于开始和结束的DataStream

一般用于学习测试时编造数据时使用
1.env.fromElements(可变参数);
2.env.fromColletion(各种集合);
3.env.fromSequence(开始,结束);

基于本地集合

package com.bigdata.source;import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class _01YuDingYiSource {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();// 各种获取数据的SourceDataStreamSource<String> dataStreamSource = env.fromElements("hello world txt", "hello nihao kongniqiwa");dataStreamSource.print();// 演示一个错误的//DataStreamSource<Object> dataStreamSource2 = env.fromElements("hello", 1,3.0f);//dataStreamSource2.print();DataStreamSource<Tuple2<String, Integer>> elements = env.fromElements(Tuple2.of("张三", 18),Tuple2.of("lisi", 18),Tuple2.of("wangwu", 18));elements.print();// 有一个方法,可以直接将数组变为集合  复习一下数组和集合以及一些非常常见的APIString[] arr = {"hello","world"};System.out.println(arr.length);System.out.println(Arrays.toString(arr));List<String> list = Arrays.asList(arr);System.out.println(list);env.fromElements(Arrays.asList(arr),Arrays.asList(arr),Arrays.asList(arr)).print();// 第二种加载数据的方式// Collection 的子接口只有 Set 和 ListArrayList<String> list1 = new ArrayList<>();list1.add("python");list1.add("scala");list1.add("java");DataStreamSource<String> ds1 = env.fromCollection(list1);DataStreamSource<String> ds2 = env.fromCollection(Arrays.asList(arr));// 第三种DataStreamSource<Long> ds3 = env.fromSequence(1, 100);ds3.print();// execute 下面的代码不运行,所以,这句话要放在最后。env.execute("获取预定义的Source");}
}

可以在代码中指定并行度

l 指定全局并行度:

env.setParallelism(12);

l 获得全局并行度:

env.getParallelism();

指定算子设置并行度:

获取指定算子并行度:

eventSource.getParallelism();

基于本地文件

package com.bigdata.source;import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class _02YuDingYiSource {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();// 获取并行度System.out.println(env.getParallelism());// 讲第二种Source File类型的// 给了一个相对路径,说路径不对,老闫非要写,我咋办?// 相对路径,转绝对路径File file = new File("datas/wc.txt");File file2 = new File("./");System.out.println(file.getAbsoluteFile());System.out.println(file2.getAbsoluteFile());DataStreamSource<String> ds1 = env.readTextFile("datas/wc.txt");ds1.print();// 还可以获取hdfs路径上的数据DataStreamSource<String> ds2 = env.readTextFile("hdfs://bigdata01:9820/home/a.txt");ds2.print();// execute 下面的代码不运行,所以,这句话要放在最后。env.execute("获取预定义的Source");}
}

基于网络套接字(socketTextStream)

socketTextStream(String hostname, int port) 方法是一个非并行的Source,该方法需要传入两个参数,第一个是指定的IP地址或主机名,第二个是端口号,即从指定的Socket读取数据创建DataStream。该方法还有多个重载的方法,其中一个是socketTextStream(String hostname, int port, String delimiter, long maxRetry),这个重载的方法可以指定行分隔符和最大重新连接次数。这两个参数,默认行分隔符是”\n”,最大重新连接次数为0。

提示:

如果使用socketTextStream读取数据,在启动Flink程序之前,必须先启动一个Socket服务,为了方便,Mac或Linux用户可以在命令行终端输入nc -lk 8888启动一个Socket服务并在命令行中向该Socket服务发送数据。Windows用户可以在百度中搜索windows安装netcat命令。

通过网盘分享的文件:netcat-win32-1.11.zip

如果是windows平台:nc -lp 8888

import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;public class SourceDemo02_Socket {public static void main(String[] args) throws Exception {//TODO 1.env-准备环境StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setRuntimeMode(RuntimeExecutionMode.AUTOMATIC);//TODO 2.source-加载数据DataStream<String> socketDS = env.socketTextStream("bigdata01", 8889);//TODO 3.transformation-数据转换处理//3.1对每一行数据进行分割并压扁DataStream<String> wordsDS = socketDS.flatMap(new FlatMapFunction<String, String>() {@Overridepublic void flatMap(String value, Collector<String> out) throws Exception {String[] words = value.split(" ");for (String word : words) {out.collect(word);}}});//3.2每个单词记为<单词,1>DataStream<Tuple2<String, Integer>> wordAndOneDS = wordsDS.map(new MapFunction<String, Tuple2<String, Integer>>() {@Overridepublic Tuple2<String, Integer> map(String value) throws Exception {return Tuple2.of(value, 1);}});//3.3分组KeyedStream<Tuple2<String, Integer>, String> keyedDS = wordAndOneDS.keyBy(new KeySelector<Tuple2<String, Integer>, String>() {@Overridepublic String getKey(Tuple2<String, Integer> value) throws Exception {return value.f0;}});//3.4聚合SingleOutputStreamOperator<Tuple2<String, Integer>> result = keyedDS.sum(1);//TODO 4.sink-数据输出result.print();//TODO 5.execute-执行env.execute();}
}

(二)自定义 Source 示例

SourceFunction:非并行数据源(并行度只能=1) --接口

RichSourceFunction:多功能非并行数据源(并行度只能=1) --类

ParallelSourceFunction:并行数据源(并行度能够>=1) --接口

RichParallelSourceFunction:多功能并行数据源(并行度能够>=1) --类 【建议使用的】

简单自定义非并行 Source(实现 SourceFunction)

package com.bigdata.day02;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.ParallelSourceFunction;
import org.apache.flink.streaming.api.functions.source.RichParallelSourceFunction;
import org.apache.flink.streaming.api.functions.source.RichSourceFunction;
import org.apache.flink.streaming.api.functions.source.SourceFunction;import java.util.Random;
import java.util.UUID;/*** 需求: 每隔1秒随机生成一条订单信息(订单ID、用户ID、订单金额、时间戳)* 要求:* - 随机生成订单ID(UUID)* - 随机生成用户ID(0-2)* - 随机生成订单金额(0-100)* - 时间戳为当前系统时间*/@Data  // set get toString
@AllArgsConstructor
@NoArgsConstructor
class OrderInfo{private String orderId;private int uid;private int money;private long timeStamp;
}
// class MySource extends RichSourceFunction<OrderInfo> {
//class MySource extends RichParallelSourceFunction<OrderInfo> {
class MySource implements SourceFunction<OrderInfo> {boolean flag = true;@Overridepublic void run(SourceContext ctx) throws Exception {// 源源不断的产生数据Random random = new Random();while(flag){OrderInfo orderInfo = new OrderInfo();orderInfo.setOrderId(UUID.randomUUID().toString());orderInfo.setUid(random.nextInt(3));orderInfo.setMoney(random.nextInt(101));orderInfo.setTimeStamp(System.currentTimeMillis());ctx.collect(orderInfo);Thread.sleep(1000);// 间隔1s}}// source 停止之前需要干点啥@Overridepublic void cancel() {flag = false;}
}
public class CustomSource {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();env.setParallelism(2);// 将自定义的数据源放入到env中DataStreamSource dataStreamSource = env.addSource(new MySource())/*.setParallelism(1)*/;System.out.println(dataStreamSource.getParallelism());dataStreamSource.print();env.execute();}}


 自定义并行 Source(实现 ParallelSourceFunction)

import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.ParallelSourceFunction;import java.util.UUID;/*** 自定义多并行度Source*/
public class CustomerSourceWithParallelDemo {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();DataStreamSource<String> mySource = env.addSource(new MySource()).setParallelism(6);mySource.print();env.execute();}public static class MySource implements ParallelSourceFunction<String> {@Overridepublic void run(SourceContext<String> ctx) throws Exception {ctx.collect(UUID.randomUUID().toString());/*如果不设置无限循环可以看出,设置了多少并行度就打印出多少条数据*/}@Overridepublic void cancel() {}}
}


自定义多功能并行 Source(实现 RichParallelSourceFunction)

import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.RichParallelSourceFunction;import java.util.UUID;/*** 自定义一个RichParallelSourceFunction的实现*/
public class CustomerRichSourceWithParallelDemo {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();DataStreamSource<String> mySource = env.addSource(new MySource()).setParallelism(6);mySource.print();env.execute();}/*Rich 类型的Source可以比非Rich的多出有:- open方法,实例化的时候会执行一次,多个并行度会执行多次的哦(因为是多个实例了)- close方法,销毁实例的时候会执行一次,多个并行度会执行多次的哦- getRuntime方法可以获得当前的Runtime对象(底层API)*/public static class MySource extends RichParallelSourceFunction<String> {@Overridepublic void open(Configuration parameters) throws Exception {super.open(parameters);System.out.println("open......");}@Overridepublic void close() throws Exception {super.close();System.out.println("close......");}@Overridepublic void run(SourceContext<String> ctx) throws Exception {ctx.collect(UUID.randomUUID().toString());}@Overridepublic void cancel() {}}
}

三、Kafka Source 应用

Kafka 作为常用消息队列,与 Flink 集成紧密。使用时需添加依赖

<dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-kafka_2.11</artifactId><version>${flink.version}</version>
</dependency>

并配置相关属性,如下示例展示从 Kafka 主题读取数据并筛选含特定字样消息后打印。

创建一个topic1 这个主题:
 

cd /opt/installs/kafka3/bin/kafka-topics.sh --bootstrap-server bigdata01:9092 --create --partitions 1 --replication-factor 3 --topic topic1通过控制台向topic1发送消息:
bin/kafka-console-producer.sh  --bootstrap-server bigdata01:9092 --topic topic1

import org.apache.flink.api.common.functions.FilterFunction;
import org.apache.flink.api.common.serialization.SimpleStringSchema;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer;import java.util.Properties;public class KafkaSource {public static void main(String[] args) throws Exception {StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();Properties properties = new Properties();properties.setProperty("bootstrap.servers", "bigdata01:9092");properties.setProperty("group.id", "g1");FlinkKafkaConsumer<String> kafkaSource = new FlinkKafkaConsumer<>("topic1", new SimpleStringSchema(), properties);DataStreamSource<String> dataStreamSource = env.addSource(kafkaSource);dataStreamSource.filter(new FilterFunction<String>() {@Overridepublic boolean filter(String word) throws Exception {return word.contains("success");}}).print();env.execute();}
}

四、总结

        掌握 Flink 普通 API 里 Source 的各类使用方式,无论是预定义 Source 快速搭建测试数据场景、灵活运用并行度设置优化资源,还是对接 Kafka 这类外部数据源,都是构建高效、稳定大数据处理管道的关键基石。后续可深入各部分细节实践,深挖性能调优等进阶玩法,让 Flink 在数据处理之旅中大放异彩。希望这篇文章能助大家在 Flink Source 使用上理清思路、顺利上手,开启大数据流式计算的精彩探索!

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

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

相关文章

【三维生成】Edify 3D:可扩展的高质量的3D资产生成(英伟达)

标题&#xff1a;Edify 3D: Scalable High-Quality 3D Asset Generation 项目&#xff1a;https://research.nvidia.com/labs/dir/edify-3d demo&#xff1a;https://build.nvidia.com/Shutterstock/edify-3d 文章目录 摘要一、前言二、多视图扩散模型2.1.消融研究 三、重建模型…

Android Framework禁止弹出当前VOLTE不可用的提示窗口

文章目录 VoLTE简介VoLTE 的优势 当前VOLTE不可用的弹窗弹窗代码定位屏蔽弹出窗口 VoLTE简介 VoLTE&#xff08;Voice over LTE&#xff09;是一种基于4G LTE网络的语音通话技术。它允许用户在4G网络上进行高质量的语音通话和视频通话&#xff0c;而不需要回落到2G或3G网络。V…

微信小程序生命周期详解

一、全局生命周期 微信小程序的全局生命周期指的是小程序从启动到销毁期间经历的一系列阶段和事件。全局生命周期主要在 App() 构造器中定义&#xff0c;包括以下几个阶段&#xff1a; onLaunch&#xff1a;小程序初始化完成时触发&#xff0c;全局只触发一次。onShow&#x…

Element UI 打包探索【3】

目录 第九个命令 node build/bin/gen-cssfile gulp build --gulpfile packages/theme-chalk/gulpfile.js cp-cli packages/theme-chalk/lib lib/theme-chalk 至此&#xff0c;dist命令完成。 解释why Element UI 打包探索【1】里面的why Element UI 打包探索【2】里面…

去哪儿大数据面试题及参考答案

Hadoop 工作原理是什么&#xff1f; Hadoop 是一个开源的分布式计算框架&#xff0c;主要由 HDFS&#xff08;Hadoop 分布式文件系统&#xff09;和 MapReduce 计算模型两部分组成 。 HDFS 工作原理 HDFS 采用主从架构&#xff0c;有一个 NameNode 和多个 DataNode。NameNode 负…

深度学习中的梯度下降算法:详解与实践

梯度下降算法是深度学习领域最基础也是最重要的优化算法之一。它驱动着从简单的线性回归到复杂的深度神经网络模型的训练和优化。作为深度学习的核心工具&#xff0c;梯度下降提供了调整模型参数的方法&#xff0c;使得预测的结果逐步逼近真实值。本文将从梯度下降的基本原理出…

C++ ADL参数依赖查找

自以为作为一个C老鸟&#xff0c;对C里面各种概念应该都比较熟悉了&#xff0c;但是今天看书的时候又学到了一个装逼的概念ADL&#xff0c;本着学C装逼装到底的精神&#xff0c;就把这个概念学习了一番。 ADL 的工作原理 在C中&#xff0c;ADL 是 Argument-Dependent Lookup …

低功耗墒情监测站产品详解 如何助力高标准农田项目发展

一、产品概述 低功耗墒情监测站是一款集成了传感、无线通信、处理与控制等物联网技术的先进设备。它利用高精度传感器实时测量土壤墒情&#xff08;即土壤水分含量&#xff09;&#xff0c;并通过物联网技术将数据传输至云平台。这一创新设计无需铺设专门的通信线路&#xff0c…

VM+Ubuntu18.04+XSHELL+VSCode环境配置

前段时间换了新电脑&#xff0c;准备安装Linux学习环境&#xff1a;VM虚拟机、Ubuntu18.04操作系统、XSHELL、XFTP远程连接软件、VSCode编辑器等&#xff0c;打算把安装过程记录一下。 1. 虚拟机介绍 为什么要用虚拟机&#xff1f; 想学习Linux操作系统&#xff0c;一般有3种…

《Opencv》基础操作<1>

目录 一、Opencv简介 主要特点&#xff1a; 应用领域&#xff1a; 二、基础操作 1、模块导入 2、图片的读取和显示 &#xff08;1&#xff09;、读取 &#xff08;2&#xff09;、显示 3、 图片的保存 4、获取图像的基本属性 5、图像转灰度图 6、图像的截取 7、图…

【Android】ARouter的使用及源码解析

文章目录 简介介绍作用 原理关系 使用添加依赖和配置初始化SDK添加注解在目标界面跳转界面不带参跳转界面含参处理返回结果 源码基本流程getInstance()build()navigation()_navigation()Warehouse ARouter初始化init帮助类根帮助类组帮助类 completion 总结 简介 介绍 ARouter…

国内首家! 阿里云人工智能平台 PAI 通过 ITU 国际标准测评

近日&#xff0c;阿里云人工智能平台 PAI 顺利通过中国信通院组织的 ITU-T AICP-GA&#xff08;Technical Specification for Artificial Intelligence Cloud Platform&#xff1a;General Architecture&#xff09;国际标准和《智算工程平台能力要求》国内标准一致性测评&…

SpringBoot文件上传之秒传、断点续传、分片上传

一 文件上传的常见场景 在日常开发中&#xff0c;文件上传的场景多种多样。比如&#xff0c;在线教育平台上的视频资源上传&#xff0c;社交平台上的图片分享&#xff0c;以及企业内部的知识文档管理等。这些场景对文件上传的要求也各不相同&#xff0c;有的追求速度&#xff…

力扣 最长回文字串-5

最长回文字串-5 //双指针&#xff0c;暴力解法 class Solution { public:bool is(string s, int l, int r) // 判断是否为回文{while (l < r) {if (s[l] ! s[r]) {return false;}l;r--;}return true;}string longestPalindrome(string s) {int Max 0;//用来判断找出最长字…

【算法】快速求出 n 最低位的 1

Leetcode 2438. 二的幂数组中查询范围内的乘积 先展示算法具体实现 while (n) {int lowbit n & (-n);powers.push_back(lowbit);n ^ lowbit; }这段代码的核心是通过 n & (-n) 计算出 n 的 最低位的 1&#xff08;即最右边的 1&#xff09; -n 是 n 的二进制补码表…

数据抽取平台pydatax使用案例---11个库项目使用

数据抽取平台pydatax&#xff0c;前期项目做过介绍&#xff1a; 1&#xff0c;数据抽取平台pydatax介绍--实现和项目使用 项目2&#xff1a; 客户有9个分公司&#xff0c;用的ERP有9套&#xff0c;有9个库&#xff0c;不同版本&#xff0c;抽取的同一个表字段长度有不一样&…

.NET9 - Swagger平替Scalar详解(四)

书接上回&#xff0c;上一章介绍了Swagger代替品Scalar&#xff0c;在使用中遇到不少问题&#xff0c;今天单独分享一下之前Swagger中常用的功能如何在Scalar中使用。 下面我们将围绕文档版本说明、接口分类、接口描述、参数描述、枚举类型、文件上传、JWT认证等方面详细讲解。…

shiny动态生成颜色选择器并将其用于绘图

在 Shiny 中使用 uiOutput 和 renderUI 动态生成 UI 控件是一种灵活的方法。结合 uiOutput(ns("colorSelectors")) 的用法&#xff0c;可以实现动态生成颜色选择器&#xff0c;并响应用户选择进行绘图或更新显示。 代码 library(shiny) library(colourpicker)# UI …

【单点知识】基于PyTorch进行模型部署

文章目录 0. 前言1. 模型导出1.1 TorchScript1.1.1 使用 torch.jit.trace1.1.2 使用 torch.jit.script 1.2 ONNX1.2.1 导出为 ONNX 格式 1.3 导出后的模型加载1.3.1 加载 TorchScript 模型1.3.2 加载 ONNX 模型 2. 模型优化2.1 模型量化2.2 模型剪枝 3. 服务化部署3.1 Flask 部…

‌Kotlin中的?.和!!主要区别

目录 1、?.和!!介绍 2、使用场景和最佳实践 3、代码示例和解释 1、?.和!!介绍 ‌Kotlin中的?.和!!主要区别在于它们对空指针的处理方式。‌ ‌?.&#xff08;安全调用操作符&#xff09;‌&#xff1a;当变量可能为null时&#xff0c;使用?.可以安全地调用其方法或属性…