响应式编程一、Reactor核心
目录
- 一、前置知识
- 1、Lambda表达式
- 2、==函数式接口 Function==
- 3、==StreamAPI==
- 4、Reactive-Stream
- 1)几个实际的问题
- 2)Reactive-Stream是什么?
- 3)==核心接口==
- 4)处理器 Processor
- 5)总结
- 二、Reactor核心
- 1、Reactor
- 1)介绍
- 2)响应式编程
- 3)Reactor核心特性
- 1、Mono和Flux
- 2、subscribe()
- 3、流的取消
- 4、BaseSubscriber
- 5、背压(Backpressure )和请求重塑(Reshape Requests)
- 6、以编程的方式创建队列
- 7、handle()的使用
- 8、自定义线程调度
课程内容
一、前置知识
1、Lambda表达式
interface MyInterface {int sum(int i, int j);
}interface MyHaha {int haha();default int heihei() {return 2;}; //默认实现
}@FunctionalInterface //检查注解,帮我们快速检查我们写的接口是否函数式接口
interface MyHehe {int hehe(int i);}/*** lambda简化函数式接口实例创建** @param args*/public static void aaaa(String[] args) {//1、自己创建实现类对象MyInterface myInterface = new MyInterfaceImpl();System.out.println(myInterface.sum(1, 2));//2、创建匿名实现类MyInterface myInterface1 = new MyInterface() {@Overridepublic int sum(int i, int j) {return i * i + j * j;}};
// System.out.println(myInterface1.sum(2, 3));//冗余写法//3、lambda表达式:语法糖 参数列表 + 箭头 + 方法体MyInterface myInterface2 = (x, y) -> {return x * x + y * y;};System.out.println(myInterface2.sum(2, 3));}//参数位置最少情况MyHaha myHaha = () -> {return 1;};MyHehe myHehe = y -> {return y * y;};MyHehe hehe2 = y -> y - 1;//总结://1)、参数类型可以不写,只写(参数名),参数变量名随意定义;// 参数表最少可以只有一个 (),或者只有一个参数名;//2、方法体如果只有一句话,{} 可以省略
2、函数式接口 Function
接口中有且只有一个未实现的方法,这个接口就叫做函数式接口
函数式接口的出入参定义:
1、有入参,无出参【消费者】BiConsumer
BiConsumer<String,String> function = (a,b)->{ //能接受两个入参System.out.println("哈哈:"+a+";呵呵:"+b);};function.accept("1","2");
2、有入参,有出参【多功能函数】: Function
Function<String,Integer> function = (String x) -> Integer.parseInt(x);System.out.println(function.apply("2"));
3、无入参,无出参【普通函数】:
Runnable runnable = () -> System.out.println("aaa");
new Thread(runnable).start();
4、无入参 ,有出参【提供者】: supplier
Supplier<String> supplier = ()-> UUID.randomUUID().toString();
String s = supplier.get();
System.out.println(s);
java.util.function包下的所有function定义:
● Consumer: 消费者
● function: 功能函数
● Supplier: 提供者
● Predicate: 断言
get/test/apply/accept调用的函数方法;
3、StreamAPI
中间操作:Intermediate Operations
- filter:过滤; 挑出我们用的元素
- map: 映射: 一一映射,a 变成 b
- mapToInt、mapToLong、mapToDouble
- flatMap:一对多映射
filter、 map、mapToInt、mapToLong、mapToDouble flatMap、flatMapToInt、flatMapToLong、flatMapToDouble mapMulti、mapMultiToInt、mapMultiToLong、mapMultiToDouble、 parallel、unordered、onClose、sequential distinct、sorted、peek、limit、skip、takeWhile、dropWhile、
终止操作:Terminal Operation
forEach、forEachOrdered、toArray、reduce、collect、toList、min、 max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator
4、Reactive-Stream
1)几个实际的问题
当请求量巨大的时候,tomcat会被压垮,此时就需要采取背压的策略,让tomcat根据自己的能力主动去消费请求。
服务器核心数固定时,多线程情况下:线程越多越好吗?
当核心数固定时,线程并不是越多越好,操作系统是分时间片执行任务的,当线程越多时,线程间的切换就越频繁,导致cpu性能消耗越多。
2)Reactive-Stream是什么?
Reactive-Streams 是一个标准规范,定义了异步数据流处理的 API 和行为规则,专注于解决异步流式数据的**背压(Backpressure)**问题。
主要特性
- 异步:通过非阻塞方式处理数据流。
- 流式处理:支持连续数据流的逐步消费,避免一次性加载大量数据。
- 背压机制:允许消费者控制生产者的速率,防止消费者被超量数据淹没。
- 非阻塞:在处理数据时不阻塞线程,提高资源利用率。
背压机制(Backpressure)
Reactive-Streams 的核心之一是通过 Subscription 提供背压支持。
消费者可以通过 request(n) 方法控制生产者的生产速率。
如果消费者处理能力不足,可以减少请求数据量,避免内存溢出或阻塞。
使用场景
事件流处理:如消息队列、用户事件。
高性能网络请求:如 RESTful API、WebSocket。
大数据流处理:需要逐步消费大规模数据的场景。
异步系统集成:将不同系统间的数据流通过异步方式连接起来。
3)核心接口
- Publisher:发布者;产生数据流
- Subscriber:订阅者; 消费数据流
- Subscription:订阅关系;
订阅关系是发布者和订阅者之间的关键接口。订阅者通过订阅来表示对发布者产生的数据的兴趣。订阅者可以请求一定数量的元素,也可以取消订阅。 - Processor:处理器;
处理器是同时实现了发布者和订阅者接口的组件。它可以接收来自一个发布者的数据,进行处理,并将结果发布给下一个订阅者。处理器在Reactor中充当中间环节,代表一个处理阶段,允许你在数据流中进行转换、过滤和其他操作。
【扩展】
以前的编程模型是命令式编程: 过程编程,全自定义
流式编程是响应式|声明式编程,说清楚要干什么,最终结果要怎么样
public class MyFlowDemo {public static void main(String[] args) {// 1、定义一个发布者,发布数据SubmissionPublisher<String> publisher = new SubmissionPublisher<>();//3、定义一个订阅者; 订阅者感兴趣发布者的数据;Flow.Subscriber<String> subscriber = new Flow.Subscriber<String>() {private Flow.Subscription subscription;@Override //在订阅时 onXxxx:在xxx事件发生时,执行这个回调public void onSubscribe(Flow.Subscription subscription) {System.out.println(Thread.currentThread() + "订阅开始了:" + subscription);this.subscription = subscription;//从上游请求一个数据subscription.request(1);}@Override //在下一个元素到达时; 执行这个回调; 接受到新数据public void onNext(String item) {System.out.println(Thread.currentThread() + "订阅者,接受到数据:" + item);//从上游请求一个数据subscription.request(1);}@Override //在错误发生时,public void onError(Throwable throwable) {System.out.println(Thread.currentThread() + "订阅者,接受到错误信号:" + throwable);}@Override //在完成时public void onComplete() {System.out.println(Thread.currentThread() + "订阅者,接受到完成信号:");}};publisher.subscribe(subscriber);for (int i = 0; i < 10; i++) {publisher.submit("p-" + i);}try {Thread.sleep(20000);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
4)处理器 Processor
public class FlowDemo {//定义流中间操作处理器; 只用写订阅者的接口static class MyProcessor extends SubmissionPublisher<String> implements Flow.Processor<String,String> {private Flow.Subscription subscription; //保存绑定关系@Overridepublic void onSubscribe(Flow.Subscription subscription) {System.out.println("processor订阅绑定完成");this.subscription = subscription;subscription.request(1); //找上游要一个数据}@Override //数据到达,触发这个回调public void onNext(String item) {System.out.println("processor拿到数据:"+item);//再加工item += ":哈哈";submit(item);//把我加工后的数据发出去subscription.request(1); //再要新数据}@Overridepublic void onError(Throwable throwable) {}@Overridepublic void onComplete() {}}/*** 1、Publisher:发布者* 2、Subscriber:订阅者* 3、Subscription: 订阅关系* 4、Processor: 处理器* @param args*///发布订阅模型:观察者模式,public static void main(String[] args) throws InterruptedException {//1、定义一个发布者; 发布数据;SubmissionPublisher<String> publisher = new SubmissionPublisher<>();//2、定一个中间操作: 给每个元素加个 哈哈 前缀MyProcessor myProcessor1 = new MyProcessor();//3、定义一个订阅者; 订阅者感兴趣发布者的数据;Flow.Subscriber<String> subscriber = new Flow.Subscriber<String>() {private Flow.Subscription subscription;@Override //在订阅时 onXxxx:在xxx事件发生时,执行这个回调public void onSubscribe(Flow.Subscription subscription) {System.out.println(Thread.currentThread()+"订阅开始了:"+subscription);this.subscription = subscription;//从上游请求一个数据subscription.request(1);}@Override //在下一个元素到达时; 执行这个回调; 接受到新数据public void onNext(String item) {System.out.println(Thread.currentThread()+"订阅者,接受到数据:"+item);if(item.equals("p-7")){subscription.cancel(); //取消订阅}else {subscription.request(1);}}@Override //在错误发生时,public void onError(Throwable throwable) {System.out.println(Thread.currentThread()+"订阅者,接受到错误信号:"+throwable);}@Override //在完成时public void onComplete() {System.out.println(Thread.currentThread()+"订阅者,接受到完成信号:");}};//4、绑定发布者和订阅者publisher.subscribe(myProcessor1); //此时处理器相当于订阅者myProcessor1.subscribe(subscriber); //此时处理器相当于发布者//绑定操作;就是发布者,记住了所有订阅者都有谁,有数据后,给所有订阅者把数据推送过去。// publisher.subscribe(subscriber);for (int i = 0; i < 10; i++) {//发布10条数据if(i == 5){
// publisher.closeExceptionally(new RuntimeException("5555"));}else {publisher.submit("p-"+i);}//publisher发布的所有数据在它的buffer区;//中断
// publisher.closeExceptionally();}//ReactiveStream//jvm底层对于整个发布订阅关系做好了 异步+缓存区处理 = 响应式系统;//发布者通道关闭publisher.close();// publisher.subscribe(subscriber2);//发布者有数据,订阅者就会拿到Thread.sleep(20000);}
}
5)总结
二、Reactor核心
响应式编程:
1、底层:基于数据缓冲队列 + 消息驱动模型 + 异步回调机制
2、编码:流式编程 + 链式调用 + 声明式API
3、效果:优雅全异步 + 消息实时处理 + 高吞吐量 + 占用少量资源
回调机制:类似于SpringBoot的事件机制,在SpringBoot应用的启动过程中触发事件。
1、Reactor
1)介绍
Reactor 是一个用于在JVM构建非阻塞应用的响应式编程框架 !
2)响应式编程
3)Reactor核心特性
1、Mono和Flux
Mono: 0|1 数据流
Flux: N数据流
响应式流:元素(内容) + 信号(完成/异常);
2、subscribe()
传递钩子函数
flux.subscribe(v-> System.out.println("v = " + v), //流元素消费throwable -> System.out.println("throwable = " + throwable), //感知异常结束()-> System.out.println("流结束了...") //感知正常结束
);
自定义消费者
flux.subscribe(new BaseSubscriber<String>() {// 生命周期钩子1: 订阅关系绑定的时候触发@Overrideprotected void hookOnSubscribe(Subscription subscription) {// 流被订阅的时候触发System.out.println("绑定了..."+subscription);//找发布者要数据request(1); //要1个数据
// requestUnbounded(); //要无限数据}@Overrideprotected void hookOnNext(String value) {System.out.println("数据到达,正在处理:"+value);request(1); //要1个数据}// hookOnComplete、hookOnError 二选一执行@Overrideprotected void hookOnComplete() {System.out.println("流正常结束...");}@Overrideprotected void hookOnError(Throwable throwable) {System.out.println("流异常..."+throwable);}@Overrideprotected void hookOnCancel() {System.out.println("流被取消...");}@Overrideprotected void hookFinally(SignalType type) {System.out.println("最终回调...一定会被执行");}});
3、流的取消
消费者调用 cancle() 取消流的订阅;
flux.subscribe(new BaseSubscriber<String>() {// 生命周期钩子1: 订阅关系绑定的时候触发@Overrideprotected void hookOnSubscribe(Subscription subscription) {// 流被订阅的时候触发System.out.println("绑定了..."+subscription);//找发布者要数据request(1); //要1个数据
// requestUnbounded(); //要无限数据}@Overrideprotected void hookOnNext(String value) {System.out.println("数据到达,正在处理:"+value);if(value.equals("哈哈:5")){cancel(); //取消流}request(1); //要1个数据}// hookOnComplete、hookOnError 二选一执行@Overrideprotected void hookOnComplete() {System.out.println("流正常结束...");}@Overrideprotected void hookOnError(Throwable throwable) {System.out.println("流异常..."+throwable);}@Overrideprotected void hookOnCancel() {System.out.println("流被取消...");}@Overrideprotected void hookFinally(SignalType type) {System.out.println("最终回调...一定会被执行");}});
4、BaseSubscriber
自定义消费者,推荐直接编写 BaseSubscriber 的逻辑;
5、背压(Backpressure )和请求重塑(Reshape Requests)
背压 :request(1)
@Overrideprotected void hookOnSubscribe(Subscription subscription) {request(1); //要1个数据}@Overrideprotected void hookOnNext(Integer value) {request(1); //要1个数据}
buffer:缓冲
Flux<List<Integer>> flux = Flux.range(1, 10) //原始流10个.buffer(3).log();//缓冲区:缓冲3个元素: 消费一次最多可以拿到三个元素; 凑满数批量发给消费者
//
// //一次发一个,一个一个发;
// 10元素,buffer(3);消费者请求4次,数据消费完成
6、以编程的方式创建队列
同步环境-generate
// 同步情况下创建流public void generate() {// 以编程方式创建序列
// Flux<Object> flux = Flux.generate(sink -> {
// for (int i = 0; i < 10; i++) {
// sink.next("哈哈哈" + i);
// }
// });// Flux<Object> flux = Flux.generate(() -> 0, (state, sink) -> {
// sink.next(state);
// return state + 1;
// });Flux<Object> flux = Flux.generate(() -> 0, (state, sink) -> {if (state <= 5) {sink.next(state);} else {sink.complete(); // 流创建完成}return state + 1;});flux.log().subscribe(System.out::println);}
流可以被取消
// 可取消public static void disposable() throws IOException {Flux<Object> flux = Flux.generate(() -> 0, (state, sink) -> {sink.next(state);return state + 1;});// disposable可以被取消Disposable disposable = flux.log().subscribe(System.out::println);new Thread(() ->{try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}disposable.dispose();}).start();System.in.read();}
多线程-create
异步创建flux对象
7、handle()的使用
自定义流中元素处理规则
// 测试handle// 自定义流中元素处理规则public static void handle() {Flux.range(1,10).handle((value, sink)->{System.out.println("拿到的值:" + value);String v = "转换" + value;sink.next(v);}).subscribe(System.out::println);}
8、自定义线程调度
指定发布者和订阅者的处理线程
// 自定义线程调度public static void custom() {Scheduler s = Schedulers.newParallel("parallel-scheduler", 4);final Flux<String> flux = Flux.range(1, 2).map(i -> 10 + i).log().publishOn(s) // 改变发布者的线程
// .subscribeOn() //改变订阅者的线程.map(i -> "value " + i);//只要不指定线程池,默认发布者用的线程就是订阅者的线程;new Thread(() -> flux.subscribe(System.out::println)).start();}
相关文章:

响应式编程一、Reactor核心
目录 一、前置知识1、Lambda表达式2、函数式接口 Function3、StreamAPI4、Reactive-Stream1)几个实际的问题2)Reactive-Stream是什么?3)核心接口4)处理器 Processor5)总结 二、Reactor核心1、Reactor1&…...

uniapp+vue3+ts请求接口封装
1.安装luch-request yarn add luch-requestnpm install luch-request2.新建文件src/utils/request.ts 需要自己修改config.baseURL和token(获取存储的token) // import HttpRequest from luch-request; import type { HttpRequestConfig, HttpRespons…...

【计算机网络】实验4:生成树协议STP的功能以及虚拟局域网VLAN
实验 4:生成树协议STP的功能以及虚拟局域网VLAN 一、 实验目的 加深对生成树协议STP的功能的理解。 了解虚拟局域网VLAN。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、验证交换机生成树协议STP的功能 (1) 第一步:构建网络拓…...

基于Matlab BP神经网络的电力负荷预测模型研究与实现
随着电力系统的复杂性和规模的不断增长,准确的电力负荷预测对于电网的稳定性和运行效率至关重要。传统的负荷预测方法依赖于历史数据和简单的统计模型,但这些方法在处理非线性和动态变化的负荷数据时,表现出较大的局限性。近年来,…...

java 21 多线程
1.相关概念 进程: 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷配新的内存空间。 进程是程序的一次执行过程&#…...

Rust学习笔记_07——枚举和范围
Rust学习笔记_04——引用 Rust学习笔记_05——控制流(1) Rust学习笔记_06——控制流(2) 文章目录 1. 枚举1.1基础1.2 给枚举变体起个“别名”1.3 枚举与匹配(match) 2. 范围2.1 介绍2.2 半开区间范围2.3 包含范围的语法糖2.4 步长范围(Range …...

40分钟学 Go 语言高并发:服务性能调优实战
服务性能调优实战 一、性能优化实战概述 优化阶段主要内容关键指标重要程度瓶颈定位收集性能指标,确定瓶颈位置CPU、内存、延迟、吞吐量⭐⭐⭐⭐⭐代码优化优化算法、并发、内存使用代码执行时间、内存分配⭐⭐⭐⭐⭐系统调优调整系统参数、资源配置系统资源利用率…...

Windows通过指令查看已安装的驱动
Windows通过指令查看已安装的驱动 在 Windows 操作系统中,有几种命令可以用来查看已安装的驱动程序。以下是常见的几种方法: 1. 使用 pnputil 查看已安装驱动程序 pnputil 是一个 Windows 内置工具,可以列出所有已安装的驱动程序包。 命令…...

Windows 11 如何配置node.js
一,官网下载 官网首页 下载最新LTS版本,比较稳定,如果想探索更新的版本去探索新的nodejs功能。 1. 下载完成后,双击运行程序,点击next 2. 勾选接受协议,点击next 3. 选择自己的安装路径(默认是…...

AWTK fscript 中的 串口 扩展函数
fscript 是 AWTK 内置的脚本引擎,开发者可以在 UI XML 文件中直接嵌入 fscript 脚本,提高开发效率。本文介绍一下 fscript 中的 ** 串口 扩展函数 ** 1.iostream_serial_create 创建串口输入输出流对象。 原型 iostream_serial_create(device) > ob…...

yolov11剪枝
思路:yolov11中的C3k2与yolov8的c2f的不同,所以与之前yolov8剪枝有稍许不同; 后续:会将剪枝流程写全,以及增加蒸馏、注意力、改loss; 注意: 1.在代码105行修改pruning.get_threshold(yolo.mo…...

智慧地图聚合(LockMap)标注系统开发说明文档
智慧地图聚合(LockMap)标注系统开发说明文档 1. 系统概述 智慧地图聚合(LockMap)标注系统是一个专为处理大规模地理信息数据而设计的综合解决方案。通过后端高效的数据管理和前端直观的地图展示,该系统能够实现对海量地理位置点的有效可视化。本项目旨在提供一个用…...

「Mac畅玩鸿蒙与硬件36」UI互动应用篇13 - 数字滚动抽奖器
本篇将带你实现一个简单的数字滚动抽奖器。用户点击按钮后,屏幕上的数字会以滚动动画的形式随机变动,最终显示一个抽奖数字。这个项目展示了如何结合定时器、状态管理和动画实现一个有趣的互动应用。 关键词 UI互动应用数字滚动动画效果状态管理用户交…...

cuda12.1版本的pytorch环境安装记录,并添加到jupyter和pycharm中
文章目录 前置准备使用anaconda prompt创建虚拟环境创建虚拟环境激活pytorch虚拟环境把pytorch下载到本地使用pip把安装包安装到pytorch环境中进入python环境检验是否安装成功将环境添加到jupyter在pycharm中使用该环境: 前置准备 安装anaconda,我的版本…...

Linux: network: nic: mellanox MRU初现
文章目录 在PPP协议了有提到过总结-吐槽MRU初现兼容问题详细的MRU的计算幸运下面这个commit缩小了幸运机会So在PPP协议了有提到过 MRU在RFC4638里有提到。但是在Linux内核里是的Ethernet是没有相关的概念。 总结-吐槽 说Mellanox的网卡驱动在2018年做了一个对进入packet的大…...

深入理解红黑树的底层逻辑
一、红黑树的定义 红黑树是一种自平衡的二叉查找树,每个节点都带有额外的颜色信息,可以是红色或黑色。红黑树的目的是通过引入颜色信息来确保树的平衡,从而提高查找、插入和删除等操作的效率。 二、红黑树的性质 每个节点都有颜色…...

【数据结构】手搓链表
一、定义 typedef struct node_s {int _data;struct node_s *_next; } node_t;typedef struct list_s {node_t *_head;node_t *_tail; } list_t;节点结构体(node_s): int _data;存储节点中的数据struct node_s *_next;:指向 node…...

ThinkPHP场景动态验证
一、缘由 今天在用thinkphp8写东西的时候发现,写验证器规则和场景优点费时间,就算用tinkphp的命令行生成也是生成一个空壳。内容还是要自己填写感觉麻烦。 就突发奇想能不能自动生成验证器,也不能是说自动生成验证器,生成验证其的…...

在M3上面搭建一套lnmp环境
下载docker-desktop 官网下载docker-desktop 切换镜像源 {"builder": {"gc": {"defaultKeepStorage": "20GB","enabled": true}},"experimental": false,"registry-mirrors": ["https://docke…...

【C++笔记】二叉搜索树
前言 各位读者朋友们大家好!上期我们讲完了面向对象编程三大属性之一的多态,这一期我们再次开始数据结构二叉搜索树的讲解。 目录 前言一. 二叉搜索树的概念二. 二叉搜索树的性能分析三. 二叉搜索树的插入四. 二叉搜索树的查找五. 二叉搜索树的删除六.…...

Fork/Join框架简介
一、Fork/Join框架简介 Fork/Join框架是Java 7引入的一个用于并行执行任务的框架,它可以将一个大任务分割成若干个小任务,并行执行这些小任务,然后将每个小任务的结果合并起来,得到大任务的结果。这种框架特别适合于能够被递归分…...

Java项目实战II基于微信小程序的电子竞技信息交流平台的设计与实现(开发文档+数据库+源码)
目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 随着互联网技术的飞速发展…...

Mysql读写分离分库分表
读写分离 什么是读写分离 读写分离主要是为了将对数据库的读写操作分散到不同的数据库节点上。 这样的话,就能够小幅提升写性能,大幅提升读性能。一般情况下,我们都会选择一主多从,也就是一台主数据库负责写,其他的从…...

B站狂神说--springboot项目学习(新建一个springboot项目)
文章目录 1.新建项目java8项目1.解决自带的idea2024无法使用java8的问题 2.新建接口3.项目打包为jar包4.使用jar包 1.新建项目java8项目 1.解决自带的idea2024无法使用java8的问题 将server.url修改为阿里云的地址:https://start.aliyun.com/ 选择Spring Web 创建…...

eltable el-table 横向 滚动条常显
又遇到了难受的问题,el-table嵌入在一个div里面,结果因为内容太多,横向、纵向我都得滚动查看! 结果发现横向滚动时只能让它纵向触底后才能进行横向操作,这就很变态,明显不符合用户操作习惯。如下图: 要先纵…...

centos8 mysql 主从复制
原理 一、一主一从 准备工作 1.主库配置 1、修改配置文件 /etc/my.cnf #mysql 服务ID,保证整个集群环境中唯一,取值范围:1-232-1,默认为 server-id1 #是否只读,1 代表只读,0代表读写 read-only0 #忽略的数据,指不需要同步的数据库 #binlog…...

【C++】入门【五】
本节目标 一、C/C内存分布 二、C语言中动态内存管理方式 三、C中动态内存管理 四、operator new与operator delete函数 五、new和delete的实现原理 六、定位new表达式(placement-new) 七、常见面试题 一、C/C内存分布 一个程序占用的内存主要有以下几部分栈区(stac…...

【React】二、状态变量useState
文章目录 1、React中的事件绑定1.1 基础事件绑定1.2 使用事件对象参数1.3 传递自定义参数1.4 同时传递事件对象和自定义参数 2、React中的组件3、useState 1、React中的事件绑定 1.1 基础事件绑定 语法:on 事件名称 { 事件处理程序 },整体上遵循驼峰…...

SQL Server中的数据处理函数:提升SQL查询能力
文章目录 前言1. 数据类型转换函数CAST()CONVERT()TRY_CAST() 和 TRY_CONVERT() 2. 数学函数ABS()CEILING()FLOOR()ROUND()POWER()SQRT() 3. 日期和时间函数GETDATE()SYSDATETIME()DATEADD()DATEDIFF()YEAR()、MONTH() 和 DAY()FORMAT() 4. 条件处理函数CASEIIF() 总结 前言 在…...

TypeScript 语言学习入门级教程五
在前面的教程中,我们已经逐步深入地学习了 TypeScript 的诸多特性,包括基础语法、类型系统、面向对象编程、装饰器以及一些高级类型等。在本教程中,我们将聚焦于 TypeScript 的模块系统、命名空间与模块的关系、声明文件以及如何在实际项目中…...