事务的隔离级别以及传播机制的详细讲解

1.为什么需要事务?

事务就是将一组操作封装成一个执行单元,要么全部执行成功,要么全部执行失败

⽐如转账分为两个操作:

  • 第⼀步操作:A 账户 -100 元
  • 第⼆步操作:B 账户 +100 元

如果没有事务,第⼀步执⾏成功了,第⼆步执⾏失败了,那么 A 账户平⽩⽆故的 100 元就“⼈间蒸发”了。⽽如果使⽤事务就可以解决这个问题,让这⼀组操作要么⼀起成功,要么⼀起失败

2.Spring 中事务的实现

Spring 中的事务操作分为两类:

  1. 编程式事务(⼿动写代码操作事务
  2. 声明式事务(利⽤注解⾃动开启和提交事务)

在讲解之前,我们先来回去一下MySql中的事务是如何进行使用的

2.1 MySQL 中的事务使用

事务在 MySQL 有 3 个重要的操作:开启事务、提交事务、回滚事务,它们对应的操作命令如下:

-- 开启事务
start transaction;
-- 业务执⾏
-- 提交事务
commit;
-- 回滚事务
rollback;

3.Spring 编程式事务(手动)

Spring 编程式事务需要手动写代码编写事务操作,所以我们只做了解即可
Spring ⼿动操作事务和上⾯ MySQL 操作事务类似,它也是有 3 个重要操作步骤:

  • 开启事务
  • 提交事务
  • 回滚事务

SpringBoot 内置了两个对象,DataSourceTransactionManager ⽤来获取事务(开启事务)、提交或回滚事务的,⽽ TransactionDefinition 是事务的属性,在获取事务的时候需要将TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus,实现代码如下:

@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionalController {

    @Autowired
    public UserService userService;

    @Autowired
    //获取 JDBC 事务管理器
    private DataSourceTransactionManager dataSourceTransactionManager;

    // 定义事务属性
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/addUser")
    public Integer addUser(String username, String password, String photo) {
        // 开启事务, 传入事物的属性(默认配置)
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        User user = new User(username, password, photo);
        Integer row = userService.insert(user);
        // 提交事务
//        dataSourceTransactionManager.commit(transactionStatus);
        // 回滚事务
        dataSourceTransactionManager.rollback(transactionStatus);
        return row;
    }
}

在这里插入图片描述
在这里插入图片描述
可以看到因为回滚了事务,所以数据库并未成功添加数据

4. Spring 声明式事务(⾃动)

声明式事务的实现很简单,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务,具体实现代码如下:

@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionalController2 {

    @Autowired
    public UserService userService;
    
    @Transactional
    @RequestMapping("/addUser")
    public Integer addUser(String username, String password, String photo) {
        User user = new User(username, password, photo);
        Integer row = userService.insert(user);
        return row;
    }
}

在这里插入图片描述在这里插入图片描述
可以看到在数据库中添加数据成功

需要注意的是
@Transactional默认只在遇到运行时异常和error时才会回滚,非运行时异常不回滚,即Exception的子类中,除了RuntimeException及其子类

4.1 @Transactional 作⽤范围

@Transactional 可以⽤来修饰⽅法或类:

  • 修饰⽅法时:需要注意只能应⽤到 public ⽅法上,否则不⽣效。推荐此种⽤法。
  • 修饰类时:表明该注解对该类中所有的 public⽅法都⽣效

4.2 @Transactional 参数说明

在这里插入图片描述

4.3事务不会⾃动回滚解决⽅案

需要注意的是 @Transactional默认只在遇到运行时异常和error时才会回滚,非运行时异常不回滚,即Exception的子类中,除了Runtime Exception及其子类,就像下面这样:
在这里插入图片描述

    @Transactional
    @RequestMapping("/addUser2")
    public Integer addUser2(String username, String password, String photo) throws IOException {
        User user = new User(username, password, photo);
        Integer row = userService.insert(user);
        try {
            int a = 10/0;
        } catch(Exception e) {
        	// 非运行时异常
            throw new IOException();
        }
        return row;
    }

运行后可以看到报错了,但是事务还是提交成功,并没有回滚
在这里插入图片描述在这里插入图片描述在这里插入图片描述

事务不会⾃动回滚解决⽅案:

解决⽅案1使用@Transactional添加参数

解决⽅案1就是可以使用添加@Transactional参数

  • rollBackFor指定需要回滚的异常类型
  • noRollBakFor指定不需要回滚的异常类型:
    /**
     * 事务不会自动回滚的解决方案,设置需要回滚的异常类型
     * @param username
     * @param password
     * @param photo
     * @return
     * @throws IOException
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/addUser3")
    public Integer addUser3(String username, String password, String photo) throws IOException {
        User user = new User(username, password, photo);
        Integer row = userService.insert(user);
        try {
            int a = 10/0;
        } catch(Exception e) {
            throw new IOException();
        }
        return row;
    }

在这里插入图片描述
在这里插入图片描述

解决⽅案2将捕获的异常重新抛出

另外如果异常被捕获了,也是不会进行事务回滚的,比如下面的代码:

    @Transactional
    @RequestMapping("/addUser3")
    public Integer addUser3(String username, String password, String photo) throws IOException {
        User user = new User(username, password, photo);
        Integer row = userService.insert(user);
        try {
            int a = 10/0;
        } catch(Exception e) {
            log.info("捕获了算数异常,不会自动回滚了");
        }
        return row;
    }

在这里插入图片描述在这里插入图片描述

可以看到异常被捕获后事务并未回滚,解决办法就是将异常重新抛出;

    @Transactional
    @RequestMapping("/addUser3")
    public Integer addUser3(String username, String password, String photo) throws IOException {
        User user = new User(username, password, photo);
        Integer row = userService.insert(user);
        try {
            int a = 10/0;
        } catch(Exception e) {
        	// 将异常重新抛出
            throw e;
        }
        return row;
    }

在这里插入图片描述
在这里插入图片描述
可以看到,捕获的异常重新抛出后,事务就会自动回滚了

4.4@Transactional ⼯作原理

@Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。如果⽬标对象实现了接⼝,默认情况下会采⽤ JDK 的动态代理,如果⽬标对象没有实现了接⼝,会使⽤ CGLIB 动态代理。
@Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途遇到了异常,则回滚事务。

1.@Transactional 实现思路预览:

在这里插入图片描述

2.@Transactional 具体执⾏细节如下图所示:

在这里插入图片描述

5.事务隔离级别

1.事务四大特性

事务有4 ⼤特性(ACID),原⼦性、持久性、⼀致性和隔离性,具体概念如下:

  • 原⼦性(Atomicity):⼀个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执⾏过程中发⽣错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执⾏过⼀样。

  • ⼀致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏,这表示写⼊的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以⾃发性地完成预定的⼯作。

  • 持久性(Isolation):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

  • 隔离性(Durability):数据库允许多个并发事务同时对其数据进⾏读写和修改的能⼒,隔离性可以防⽌多个事务并发执⾏时由于交叉执⾏⽽导致数据的不⼀致。

  • 事务隔离分为不同级别,包括读未提交(Readuncommitted)、读提交(read committed)、可重复读(repeatable read)和串⾏化(Serializable)

⽽这 4 种特性中,只有隔离性(隔离级别)是可以设置

2.为什么要设置隔离级别?

事务的隔离级别就是为了防⽌,其他的事务影响当前事务执⾏的⼀种策略
保证在并发操作下事务执行可以达到预期结果

3.MySQL 事务隔离级别有 4 种

1.READ UNCOMMITTED(读未提交)

这个级别的事务可能会读到别的事物还未提交的数据,后续别的事务可能会进行回滚,那么当前事务读到的就是脏数据,我们把这个问题称之为脏读

2.READ COMMOTTED(读已提交)

该隔离级别的事务读到的都是已经提交的事务,所以不会产生脏读问题,但是可能在不同的查询时间,有别的事物对数据进行了修改,所以导致,在别的事物修改前后当前事务读取到了不同的结果,这个问题称之为不可重复读

3.REPEATABLE READ(可重复读)是MySQL默认的隔离级别

他能确保当前事务每次查询的结果一致,但是有产生了一个新的问题,在他开启事务后,有另一个新的事物进行了插入数据操作并且成功提交,但是当前事务却查询不到,因为在当前事务中每次查询结果都是一致的,但是当前事务如果想重复插入数据也不会成功(因为数据库唯一主键约束),所以就导致了幻读现象

4.SERIALIZABLE(序列化)

事务的最高隔离级别,他会强制事务进行排序,使之不会发生冲突,从而解决了脏读,不可重复读,幻读的问题,但是因为执行效率低,所以一般不会使用

在数据库中通过以下 SQL 查询全局事务隔离级别和当前连接的事务隔离级别:

select @@global.tx_isolation,@@tx_isolation;

在这里插入图片描述

  • 脏读:⼀个事务读取到了另⼀个事务修改的数据之后,后⼀个事务⼜进⾏了回滚操作,从⽽导致第⼀个事务读取的数据是错误的。
  • 不可重复读:⼀个事务两次查询得到的结果不同,因为在两次查询中间,有另⼀个事务把数据修改了。
  • 幻读:⼀个事务两次查询中得到的结果集不同,因为在两次查询中另⼀个事务有新增了⼀部分数据。

4.Spring 中设置事务隔离级别

Spring 中事务隔离级别可以通过 @Transactional 中的 isolation 属性进⾏设置,

  1. Isolation.DEFAULT:默认的隔离级别,以连接的数据库的事务隔离级别为主。
  2. Isolation.READ_UNCOMMITTED:读未提交,可以读取到未提交的事务,存在脏读。
  3. Isolation.READ_COMMITTED:读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重
    复读。
  4. Isolation.REPEATABLE_READ:可重复读,解决了不可重复读,但存在幻读(MySQL默认级
    别)。
  5. Isolation.SERIALIZABLE:串⾏化,可以解决所有并发问题,但性能太低
    Spring 中事务隔离级别只需要设置 @Transactional ⾥的 isolation 属性即可,具体实现如下:
    在这里插入图片描述

6.Spring 事务传播机制

1. 事务传播机制是什么?

Spring 事务传播机制定义了多个包含了事务的⽅法,相互调⽤时,事务是如何在这些⽅法间进⾏传递的

2. 为什么需要事务传播机制?

  • 事务隔离级别是保证多个并发事务执⾏的可控性的(稳定性的),
  • 事务传播机制是保证⼀个事务在多个调⽤⽅法间的可控性的(稳定性的)
    在这里插入图片描述
    ⽽事务传播机制解决的是⼀个事务在多个节点(⽅法)中传递的问题,如下图所示:
    在这里插入图片描述

例⼦:像新冠病毒⼀样,它有不同的隔离⽅式(酒店隔离还是居家隔离),是为了保证疫情可控,然⽽在每个⼈的隔离过程中,会有很多个执⾏的环节,⽐如酒店隔离,需要负责⼈员运送、物品运送、消杀原⽣活区域、定时核算检查和定时送餐等很多环节,⽽事务传播机制就是保证⼀个事务在传递过程中是可靠性的,回到本身案例中就是保证每个⼈在隔离的过程中可控的

3.事务传播机制有哪些?

Spring 事务传播机制包含以下 7 种:

  1. Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。
  2. Propagation.SUPPORTS:如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。
  3. Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。
  4. Propagation.REQUIRES_NEW:表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部⽅法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部⽅法会新开启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰。
  5. Propagation.NOT_SUPPORTED:以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。
  6. Propagation.NEVER:以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。
  7. Propagation.NESTED:如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED

以上 7 种传播⾏为,可以根据是否⽀持当前事务分为以下 3 类:
在这里插入图片描述
以情侣关系为例来理解以上分类:
在这里插入图片描述

4.Spring 事务传播机制使⽤和各种场景演示

4.1创建数据库表

use mycnblog;
drop table if exists userlog;
create table userlog (
id int primary key auto_increment,
username varchar(100) not null,
createtime datetime default now(),
updatetime datetime default now()
) default charset 'utf8mb4';

4.2创建Java代码

@RestController
@RequestMapping("/trans3")
public class TransactionalController3 {

    @Autowired
    private UserService userService;
    @Autowired
    private UserLogService userLogService;

    @Transactional
    @RequestMapping("/addUser")
    public boolean addUser(String username, String password, String photo) {
        // 1.插入用户表
        User user = new User(username, password, photo);
        // 该方法也有@Transactional注解
        userService.insert(user);
        // 2.插入日志表
        UserLog userLog = new UserLog();
        userLog.setUsername(username);
        // 该方法也有@Transactional注解
        userLogService.insertLog(userLog);
        return true;
    }
}

4.3⽀持当前事务(REQUIRED)默认的事务传播机制

如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
正常情况下两个表的数据都插入成功
那么如果userlog在插入的过程中报错呢?,我们手动让他抛出异常,就像下面这样:在这里插入图片描述
我们再重新去访问url
在这里插入图片描述
可以看到报错了,数据库并未插入任何数据
在这里插入图片描述
执⾏流程描述:

  • UserService 中的保存⽅法正常执⾏完成。
  • LogService 保存⽇志程序报错,因为使⽤的是 Controller 中的事务,所以整个事务回滚。
  • 数据库中没有插⼊任何数据,也就是步骤 1 中的⽤户插⼊⽅法也回滚了

4.4不⽀持当前事务(REQUIRES_NEW)

addUser方法中的代码不变,将添加⽤户和添加⽇志的⽅法修改为 REQUIRES_NEW 不⽀持当前事务,重新创建事务,观察执⾏结果
在这里插入图片描述

4.5不⽀持当前事务,NEVER 抛异常

addUser方法中的代码不变,将添加⽤户和添加⽇志的⽅法修改为 REQUIRES_NEW 不⽀持当前事务,若存在事务,直接程序执⾏报错,观察执⾏结果
在这里插入图片描述
不允许事务,存在事务,直接程序执⾏报错,⽤户表未添加任何数据

4.6 NESTED 嵌套事务

我们先来测试正常情况下的运行结果:
在这里插入图片描述
正常情况下似乎与默认的传播机制没什么两样,但是如果是异常情况呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到同样也是一个事务都没有执行成功,此时我们在 LogService 进⾏当前事务的回滚操作
在这里插入图片描述
最终执⾏效果是:
在这里插入图片描述
没有报错,但是userinfo表插入成功,userlog表却插入失败了
在这里插入图片描述在这里插入图片描述
说明:Log 中的事务已经回滚,但是嵌套事务不会回滚嵌套之前的事务,也就是说嵌套事务可以实现部分事务回滚
我们把它改成REQUIRED再试试
在这里插入图片描述
在这里插入图片描述
此时访问出错了,并且数据库中并未添加任何数据
在这里插入图片描述
嵌套事务(NESTED)和加⼊事务(REQUIRED )的区别

  • 整个事务如果全部执⾏成功,⼆者的结果是⼀样的。
  • 如果事务执⾏到⼀半失败了,那么加⼊事务整个事务会全部回滚;⽽嵌套事务会局部回滚,不会影响上⼀个⽅法中执⾏的结果

嵌套事务只所以能够实现部分事务的回滚,是因为事务中有⼀个保存点(savepoint)的概念,嵌套事务进⼊之后相当于新建了⼀个保存点,⽽滚回时只回滚到当前保存点,因此之前的事务是不受影响的,这⼀点可以在 MySQL 的官⽅⽂档汇总找到相应的资料:
https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
⽽ REQUIRED 是加⼊到当前事务中,并没有创建事务的保存点,因此出现了回滚就是整个事务回滚,
这就是嵌套事务和加⼊事务的区别

7.总结

Spring 事务使⽤中,重点的内容有 3 个:

  1. 在 Spring 项⽬中使⽤事务,⽤两种⽅法⼿动操作和声明式⾃动提交,其中后者使⽤的最多,在⽅法上添加 @Transactional 就可以实现了。
  2. 设置事务的隔离级别 @Transactional(isolation = Isolation.SERIALIZABLE),Spring 中的事务隔离级别有 5 种。
  3. 设置事务的传播机制 @Transactional(propagation = Propagation.REQUIRED),Spring 中的事务传播级别有 7 种

事务到这里就讲解结束了,下篇博客见~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SQL-每日一题【1173. 即时食物配送 I】

题目 配送表: Delivery 如果顾客期望的配送日期和下单日期相同,则该订单称为 「即时订单」,否则称为「计划订单」。 查询即时订单所占的百分比, 保留两位小数。 查询结果如下所示。 示例 1: 解题思路 1.题目要求我们查询出顾客期望的配送日…

回归预测 | MATLAB实现SO-CNN-LSTM蛇群算法优化卷积长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现SO-CNN-LSTM蛇群算法优化卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现SO-CNN-LSTM蛇群算法优化卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现SO-CNN-LS…

Ubuntu20.04安装Autoware.universe并与Awsim联调

文章目录 引言一、安装依赖1.1 安装git1.2 克隆Autoware到本地1.3 自动安装相关依赖1.4 安装显卡驱动1.5 安装ROS2 Galactic1.6 安装ros2_dev_tools1.7 安装rmw_implementation1.8 安装pacmod1.9 安装autoware_core1.10 安装autoware universe dependencies1.11 安装pre_commit…

论文阅读-BotPercent: Estimating Twitter Bot Populations from Groups to Crowds

目录 摘要 引言 方法 数据集 BotPercent架构 实验结果 活跃用户中的Bot数量 Bot Population among Comment Sections Bot Participation in Content Moderation Votes Bot Population in Different Countries’ Politics 论文链接:https://arxiv.org/pdf/23…

解密低价正规渠道的来源:影视会员肯德基点餐直充api接口

话费充值 接口已经整合移动、联通、电信三网话费充值渠道。话费可以说是全民所需,对于平台引流,增强平台日活跃度可以提供不小的帮助。 肯德基在线点餐 接口整合了各大城市的肯德基门店,支持门店选择,在线点餐 提前点餐领取&a…

Xilinx AXI VIP使用教程

AXI接口虽然经常使用,很多同学可能并不清楚Vivado里面也集成了AXI的Verification IP,可以当做AXI的master、pass through和slave,本次内容我们看下AXI VIP当作master时如何使用。 新建Vivado工程,并新建block design,命…

设计模式-备忘录模式在Java中使用示例-象棋悔棋

场景 备忘录模式 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效 或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,当前很多软件都提供了撤销(Undo)操作&#xff0…

虚拟现实技术(VR)

目录 1.什么是虚拟现实技术 2.虚拟现实技术的由来 3.虚拟现实技术给人类带来的好处 4.虚拟现实技术未来的走向 1.什么是虚拟现实技术 虚拟现实技术(Virtual Reality,简称VR)是一种通过计算机生成的模拟环境,使用户能够身临其境…

原生html—摆脱ps、excel 在线绘制财务表格加水印(html绘制表格js加水印)

文章目录 ⭐前言⭐html标签💖table表格的属性💖实现财务报表 ⭐结束 ⭐前言 大家好,我是yma16,本文分享原生html——绘制表格报表加水印。 背景:解决没有ps的情况下使用前端html制作表格报表。 html介绍 HTML&#xf…

国内外遥感数据处理软件对比

1.国内遥感数据处理软件概况 1.1北京航天宏图信息技术股份有限公司 1.1.1公司简介 航天宏图信息技术股份有限公司成立于2008年,是国内遥感和北斗导航卫星应用服务商,致力于卫星应用软件国产化、行业应用产业化、应用服务商业化,研发并掌握了具有完全自主知识产权的PIE(Pix…

TWILIGHT靶场详解

TWILIGHT靶场详解 下载地址:https://download.vulnhub.com/sunset/twilight.7z 这是一个比较简单的靶场,拿到IP后我们扫描发现开启了超级多的端口 其实这些端口一点用都没有,在我的方法中 但是也有不同的方法可以拿权限,就需要…

el-table 设置行背景颜色 鼠标移入高亮问题处理

一、 设置行背景颜色 1. 需求描述 后端返回表格数据,有特定行数需要用颜色标识。类似于以下需求: 2. 解决方式 方式区别:row-class-name“tableRowClassName”已返回类名的形式设置样式,代码整洁,但是会鼠标高亮&#xff0c…

【ChatGLM_01】ChatGLM2-6B本地安装与部署(大语言模型)

基于本地知识库的问答 1、简介(1)ChatGLM2-6B(2)LangChain(3)基于单一文档问答的实现原理(4)大规模语言模型系列技术:以GLM-130B为例(5)新建知识库…

DevOps-GitHub/GitLab

DevOps-GitHub/GitLab GitHub是一个开源代码托管平台。基于web的Git仓库,提供共有仓库和私有仓库(私有仓库收费)。 GitLab可以创建免费私有仓库。 GitHub 为了快速操作,这里对创建仓库以及注册不做说明。 首先再GitHub上创建一…

HarmonyOS学习路之方舟开发框架—学习ArkTS语言(状态管理 二)

Prop装饰器:父子单向同步 Prop装饰的变量可以和父组件建立单向的同步关系。Prop装饰的变量是可变的,但是变化不会同步回其父组件。 概述 Prop装饰的变量和父组件建立单向的同步关系: Prop变量允许在本地修改,但修改后的变化不会…

【C++】stack | queue | priority_queue的模拟实现

stack&queue的模拟实现 stack 与 queue 作为容器适配器&#xff0c;都默认选择了 deque 作为其底层容器。 #pragma once #include <deque> using namespace std;namespace zs {template<class T, class Container deque<T>>class stack{public:void p…

C#之泛型

目录 一、概述 二、C#中的泛型 继续栈的示例 三、泛型类 &#xff08;一&#xff09;声明泛型类 &#xff08;二&#xff09;创建构造类型 &#xff08;三&#xff09;创建变量和实例 &#xff08;四&#xff09;比较泛型和非泛型栈 四、类型参数的约束 &#xff08;一…

iOS--runtime

什么是Runtime runtime是由C和C、汇编实现的一套API&#xff0c;为OC语言加入了面向对象、运行时的功能运行时&#xff08;runtime&#xff09;将数据类型的确定由编译时推迟到了运行时平时编写的OC代码&#xff0c;在程序运行过程中&#xff0c;最终会转换成runtime的C语言代…

“华为杯”研究生数学建模竞赛2019年-【华为杯】D题:汽车行驶工况构建

目录 摘 要&#xff1a; 1.问题背景与问题重述 1.1 问题背景 1.2 问题重述 2.模型假设 3.符号说明 4.问题一的求解 4.1 问题分析 4.2 异常数据的处理 4.2.1 明显错误数据的处理 4.2.2 加减速异常数据的处理 4.3 缺失数据的处理 4.3.1 数据插补处理 4.3.2 视为长期停车处理 4.3.…

64核RISC-V服务器能打了吗?

作者&#xff1a;西风烈 最近看到“澎峰科技”的微信公众号&#xff0c;看到他们发布了第一款RISC-V服务器&#xff0c;芯片是算能的SG2042&#xff0c;带64个RISC-V核心&#xff08;阿里平头哥的C910v核&#xff09;&#xff0c;2.0GHz主频&#xff0c;最大支持128GB内存。这…