Java 多线程之同步(锁)相关类总结

文章目录

    • 一、概述
    • 二、volatile 可见性/有序性
    • 三、synchronized 互拆锁/排他锁/非观锁
    • 四、DCL(Double-Checked Locking)
    • 五、CAS(Compare and Set)
    • 六、ReentrantLock 可重入锁/公平/非公平锁
    • 七、ReentrantReadWriteLock 读写锁/共享锁/排他锁
    • 八、CountDownLatch 计数等待/同步辅助类
    • 九、CyclicBarrier 并行任务/数据加载/同步辅助类
    • 十、Phaser 多阶段任务/同步辅助类
    • 十一、StampedLock 读写锁,共享锁/排他锁
    • 十二、Semaphore 信号量/限流/同步辅助类
    • 十三、Exchanger 数据交换,同步辅助类
    • 十四、LockSupport 阻塞和唤醒线程

一、概述

  • 要实现线程同步,原理就是加锁。只是看什么情况使用什么锁,以及锁的粒度问题。

二、volatile 可见性/有序性

  • 详细使用说明请看Java 多线程之 volatile。

  • 提供可见性,保证有序性。虽然提供了可见性和有序性的保证,但它并不能保证原子性。对于复合操作,如递增或递减操作,仍然需要使用其他机制,如锁或原子类来保证原子性。

  • 使用方法

    volatile int count1 = 1;
    private volatile int count2 = 2;
    volatile boolean flag1 = false;
    private volatile boolean flag2 = false;
    

三、synchronized 互拆锁/排他锁/非观锁

  • 详细使用说明请看Java 多线程之 synchronized。

  • synchronized 提供了一种简单而强大的机制来控制多个线程之间的并发访问,确保共享资源的安全性和一致性。它解决了多线程环境中的竞态条件、数据竞争和内存模型等问题,是实现线程安全的重要手段之一。

  • 作用在代码上,相当于给代码块加锁(Lock)

      	public void performTask() {// synchronized 作用于代码块synchronized (lock) {// 业务逻辑,同步代码块,对共享资源进行操作}}
    
  • 作用在方法上,相当于给整个方法加锁(Lock)

        // synchronized 作用在方法上public synchronized void increment() {// 业务逻辑,同步代码块,对共享资源进行操作}
    

四、DCL(Double-Checked Locking)

  • 详细使用说明请看Java 多线程之 DCL。

  • DCL 是 Double-Checked Locking 的缩写,是一种用于在多线程环境下延迟初始化对象的技术。它的目标是在保持高性能的同时,确保只有一个线程执行对象的初始化过程。

  • DCL 的实现通常基于以下步骤:

    1. 检查对象是否已经被创建。如果已经创建,则直接返回对象。
    2. 如果对象尚未创建,则尝试获取锁。
    3. 获取锁后,再次检查对象是否已经被创建(在获取锁之前的检查只是为了避免不必要的同步)。
    4. 如果对象尚未创建,则进行对象的创建和初始化。
    5. 释放锁。
    6. 返回对象。
  • 使用方法如下,Singleton 是一个在高并发下,多线要使用的延迟初始化单例类

    public class Singleton {private static volatile Singleton instance;private Singleton() {// 私有构造函数}public static Singleton getInstance() {if (instance == null) { // 1.检查对象是否已经被创建synchronized (Singleton.class) { // 2.尝试获取锁if (instance == null) { // 3.再次检查对象是否已经被创建instance = new Singleton();// 4.如果对象尚未创建,则进行对象的创建和初始化}}// 5.释放锁(synchronized 语句块结束自动释放锁)}return instance; // 6.返回对象}
    }
    

    需要注意的是 Singleton instance 对象的定义需要使用 volatile 关键字。

五、CAS(Compare and Set)

  • 详细使用说明请看Java 多线程之 CAS 。

  • 实现无锁优化,是自旋锁/乐观锁的实现方式。

  • CAS 是 Compare and Set(比较并设置)的缩写,是一种并发算法,用于实现多线程环境下的原子操作。

  • CAS 操作涉及三个操作数:内存位置(或称为变量的值)、期望值和新值。它的执行过程是:将内存位置的当前值与期望值进行比较。如果相等,则将新值写入内存位置;如果不相等,则说明其他线程已经修改了内存位置的值,操作失败。

  • CAS只能检测到预期值是否相等,无法感知到变量值的修改过程中是否发生了其他的并发修改,可能会引发ABA问题。

  • java.util.concurrent.atomic.Atomic* 开头的类都用 CAS 实现无锁优化,因此在多线程环境中能用这些类就尽量不用悲观锁相关类。

            AtomicBoolean atomicBoolean = new AtomicBoolean();AtomicInteger atomicInteger = new AtomicInteger();AtomicLong atomicLong = new AtomicLong();AtomicIntegerArray atomicIntegerArray = new AtomicIntegerArray(new int[5]);AtomicLongArray atomicLongArray = new AtomicLongArray(new long[5]);//AtomicIntegerFieldUpdater atomicIntegerFieldUpdater = new AtomicIntegerFieldUpdater();// 等等 ...
    

六、ReentrantLock 可重入锁/公平/非公平锁

  • 详细使用说明请看Java 多线程之 ReentrantLock。

  • ReentrantLock 是一个可重入锁,与 synchronized 关键字相比,ReentrantLock 提供了更灵活、更强大的功能,同时也更复杂。

  • 公平锁/非公平锁

    • 直接使用 ReentrantLock 的 lock 和 unlcok 方法,基本功能同 synchronized 关键字。但是他比 synchronized 强大的地方在于他可以设置为公平锁和非公平锁,以及使用可中断获取锁和超时获取锁方法。

      class XXXXXX {private ReentrantLock lock = new ReentrantLock(true); // 公平锁//private ReentrantLock lock = new ReentrantLock(false); // 非公平锁public void increment() {lock.lock(); // 获取锁// lock.lockInterruptibly(); // 获取可中断的锁// lock.tryLock(3000, TimeUnit.SECONDS);// 在指时间内获取锁try {// 业务逻辑} finally {lock.unlock();// 释放锁}}
      }
      
  • 条件变量 (Condition)

    • ReentrantLock 的条件变量(Condition)的使用,实现线程等待/通知机制。

      class BoundedQueue<T> {private Queue<T> queue = new LinkedList<>();private int capacity;private ReentrantLock lock = new ReentrantLock();private Condition notFull = lock.newCondition();private Condition notEmpty = lock.newCondition();public BoundedQueue(int capacity) {this.capacity = capacity;}public void enqueue(T item) throws InterruptedException {lock.lock();try {while (queue.size() == capacity) {// 条件1达到, 业务逻辑1等待notFull.await();}queue.add(item);// 通知业务逻辑2执行notEmpty.signalAll();} finally {lock.unlock();}}public T dequeue() throws InterruptedException {lock.lock();try {while (queue.isEmpty()) {// 条件2达到,业务逻辑2等等notEmpty.await();}T item = queue.poll();// 通知业务逻辑1执行notFull.signalAll();return item;} finally {lock.unlock();}}
      }
      

七、ReentrantReadWriteLock 读写锁/共享锁/排他锁

  • 详细使用说明请看Java 多线程之 ReentrantReadWriteLock。

  • ReentrantReadWriteLock 是Java中提供的一种读写锁实现,它允许多个线程同时读取共享资源,但在写操作时需要独占访问。它是对传统互斥锁的一种改进,可以提高并发性能。

  • 读写锁的主要目的是在读多写少的场景下,提供更高的并发性能。当多个线程只需读取共享资源时,可以同时获得读锁,从而实现并发读取。而当有线程需要对共享资源进行写操作时,它必须独占地获取写锁,在此期间,其他线程无法获取读锁或写锁,从而确保数据的一致性和完整性。

  • 获取读锁

    rwLock.readLock().lock();
    try {// 访问共享资源的读操作
    } finally {rwLock.readLock().unlock();
    }
    
  • 获取写锁

    rwLock.writeLock().lock();
    try {// 访问共享资源的写操作
    } finally {rwLock.writeLock().unlock();
    }
    

八、CountDownLatch 计数等待/同步辅助类

  • 详细使用说明请看Java 多线程之 CountDownLatch。

  • CountDownLatch 是Java中提供的一种同步工具类,用于控制多个线程之间的执行顺序和协调。

  • CountDownLatch 通过一个计数器来实现,该计数器初始化为一个正整数,表示需要等待的线程数目。每个线程执行完一定的任务后,会调用countDown()方法将计数器减1。当计数器减到0时,表示所有线程已经完成任务,等待在await()方法处的线程被唤醒,继续执行后续操作。

  • 使用方法

    int threadCount = 3;
    CountDownLatch latch = new CountDownLatch(threadCount);for (int i = 0; i < threadCount; i++) {// 启动一些子线程来执行任务Thread thread = new Thread(() -> {// 子线程执行任务System.out.println("执行业务逻辑");// 子线程任务完成,计数器减1latch.countDown();});thread.start();
    }// 主线程 等待所有线程完成任务
    latch.await();
    // 所有子线程完成任务后 主线程继续执行后续操作
    System.out.println("执行后续业务");

九、CyclicBarrier 并行任务/数据加载/同步辅助类

  • 详细使用说明请看Java 多线程之 CyclicBarrier。

  • CyclicBarrier(循环屏障)是Java并发编程中的一种同步辅助工具。它允许一组线程相互等待,直到所有线程都到达一个共同的屏障点,然后继续执行后续操作。CyclicBarrier可以用于解决多线程任务的协调和同步问题。

  • CyclicBarrier 的主要作用是使多个线程在某个点上进行同步等待所有线程都到达该点后再一起继续执行

    • 它类似于一组线程开始跑步,跑到3000米时停下等待其他线程跑完全,全部到后裁判统计分数,然后再同时开始启跑。
    • 我感觉有点像三峡大坝的船过闸一样的,假如一些船开到三峡大坝的闸内,这里他们不能过闸,但等一定数量的船后,闸门打开,这些船只开始继续航行。
    • 实际应用如下载N个文件碎片,都完成后按顺序合成一个,然后再进行分析。
  • 使用方法

    import java.util.concurrent.BrokenBarrierException;
    import java.util.concurrent.CyclicBarrier;public class CyclicBarrierExample {private static final int THREAD_COUNT = 3;public static void main(String[] args) {CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT, () -> {// 执行屏障动作(最后一个到达的线程执行该动作)。// 特别说明:能执行到这里说明,规定数量的线程(THREAD_COUNT)都执行了 barrier.await();            });for (int i = 0; i < THREAD_COUNT; i++) {Thread thread = new Thread(() -> {try {// 执行业务逻辑barrier.await(); // 线程到达屏障点,等待其他线程// 所以线程都到达屏障点,并且已经执行屏障作用后,才会执行这里的代码} catch (InterruptedException | BrokenBarrierException e) {e.printStackTrace();}});thread.start();}}
    }
    

十、Phaser 多阶段任务/同步辅助类

  • 详细使用说明请看Java 多线程之 Phaser。

  • Phaser 也是Java并发编程中的一种同步辅助工具,用于线程之间的协调和同步。它提供了比CyclicBarrier和CountDownLatch更灵活和强大的功能,可以用于更复杂的多线程协作场景。

  • Phaser的主要用途是将多个线程分为多个阶段,并在每个阶段进行同步。每个线程可以独立运行,但在特定的阶段需要等待其他线程到达屏障点。Phaser可以动态地适应线程的注册和注销,可以处理可变数量的参与者。

  • 使用方法

    import java.util.concurrent.Phaser;public class MultiPhaseTask {private static final int NUM_THREADS = 3;public static void main(String[] args) {// 注册线程可以通过构造函数的参数指定,也可以通过 phaser.register(); 方法注册线程。Phaser phaser = new Phaser(NUM_THREADS) {@Overrideprotected boolean onAdvance(int phase, int registeredParties) {System.out.println("第" + phase + "阶段完成");return false; // 返回 true 会终止 phaser}};for (int i = 0; i < NUM_THREADS; i++) {// phaser.register(); // 如果上面造函数的参数没有指定,则启用这句话来注册线程Thread thread = new Thread(() -> {// 使用 for 循环来模拟3个阶段for (int phase = 1; phase <= 3; phase++) {// 这是第 phase 阶段System.out.println("执行第 phase 阶段 任务...");               phaser.arriveAndAwaitAdvance(); // 等待其他线程到达屏障点}System.out.println("完成所有阶段");// 解除线程的注册phaser.arriveAndDeregister();});thread.start();}}
    }
    

十一、StampedLock 读写锁,共享锁/排他锁

  • 详细使用说明请看Java 多线程之 StampedLock。

  • StampedLock是Java 8引入的一种读写锁的实现,它提供了一种乐观的读锁(Optimistic Read Lock)和悲观的读锁(Pessimistic Read Lock),和写锁(Write Lock),以及对读-写冲突的解决方案。StampedLock的设计目标是在读多写少的场景下提供更高的并发性能。与传统的读写锁相比,StampedLock更加灵活和高效。

  • 与前面的 ReentrantReadWriteLock 相比,StampedLock 在某些情况下可以提供更高的性能,但并不是在所有情况下都表现更好。StampedLock 的优势主要表现在支持乐观读取机制条件等待。所以在写操作频繁而读操作较少存在大量的锁竞争的情况下,直接使用悲观读锁,性能跟ReentrantReadWriteLock是相差不大的。

  • 使用方法

    import java.util.concurrent.locks.StampedLock;public class StampedLockExample {private Object SharedData;private final StampedLock lock = new StampedLock();public void write(Object obj) {//获取写锁long stamp = lock.writeLock();try {// 执行写业务逻辑,如下SharedData = obj;} finally {// 释放写锁lock.unlockWrite(stamp);}}// 完全使用乐观读锁public Object read1() {while(true){Object result = null;// 获取乐观读锁long stamp = lock.tryOptimisticRead(); // 执行读业务逻辑,如下result = SharedData;// 验证共享数据是否被修改,如果没有被修改过,则直接返回。否则重新读if (lock.validate(stamp)) {return result;}}}// 使用乐观读锁 + 非观读锁public Object read2() {Object result = null;// 获取乐观读锁long stamp = lock.tryOptimisticRead(); // 执行读业务逻辑(这里先读一次),如下result = SharedData;// 验证共享数据是否被修改if (lock.validate(stamp)) {// 如果共享数据没有被修改过,则直接使用return result;}// 获取悲观读锁stamp = lock.readLock();try {// 执行读业务逻辑,重新读result = SharedData;} finally {// 释放写锁lock.unlockRead(stamp);}return result;}
    }
    

十二、Semaphore 信号量/限流/同步辅助类

  • 详细使用说明请看Java 多线程之 Semaphore。

  • Semaphore(信号量)是一种并发控制机制,用于控制对共享资源的访问。它维护了一个计数器,可以限制同时访问某个资源的线程数量。常用于限制同时访问某个资源的线程数量,例如控制数据库连接池的并发访问、控制线程池的并发任务数、生产者-消费者问题、读者-写者问题等。

  • 使用方法

    public class SemaphoreExample {private Semaphore semaphore = new Semaphore(5); // 允许同时访问资源的线程数量,这里设置为5,表示可以有5个线程同时访问public void accessResource() {try {semaphore.acquire(); // 获取许可证,如果有许可证,则计数器减1;如果没有可用许可证,则阻塞// 访问共享资源的代码} catch (InterruptedException e) {// 处理中断异常} finally {semaphore.release(); // 释放资源,计数器加1}}
    }
    

十三、Exchanger 数据交换,同步辅助类

  • 详细使用说明请看Java 多线程之 Exchanger。

  • Exchanger(交换器)是Java并发包中的一个工具类,用于两个线程之间交换数据。它提供了一个同步点,当两个线程都到达该点时,它们可以交换数据,并且在交换完成后继续执行。

  • 使用方法:

    import java.util.concurrent.Exchanger;public class ExchangerExample {private Exchanger<String> exchanger = new Exchanger<>();// 线程1public void thread1() {try {// 执行线程1的业务逻辑String data1 = "线程1的业务数据";String exchangedData = exchanger.exchange(data1);// exchangedData 是线程2的业务数据,在这里可以继续处理交换后的数据// 执行线程1的业务逻辑} catch (InterruptedException e) {}}// 线程2public void thread2() {try {// 执行线程2的业务逻辑String data2 = "线程2的业务数据";String exchangedData = exchanger.exchange(data2);// exchangedData 是线程1的业务数据,在这里可以继续处理交换后的数据// 执行线程2的业务逻辑} catch (InterruptedException e) {}}
    }
    

十四、LockSupport 阻塞和唤醒线程

  • 详细使用说明请看Java 多线程之 LockSupport。

  • LockSupport 是Java并发包中的一个工具类,用于线程的阻塞和唤醒。它提供了一种基于线程的许可(permit)的方式来实现线程的阻塞和唤醒,而不需要显式地使用锁。例如某个条件满足后阻塞线程,然后等待某个条件满足后再继续执行、实现线程间的协作等。

  • 使用方法

    import java.util.concurrent.locks.LockSupport;public class LockSupportExample {public static void main(String[] args) {Thread thread1 = new Thread(() -> {// 执行业务逻辑LockSupport.park(); // 阻塞当前线程// 继续执行业务逻辑});thread1.start();try {Thread.sleep(2000); // 等待2秒钟} catch (InterruptedException e) {e.printStackTrace();}LockSupport.unpark(thread1); // 唤醒 thread1 线程}
    }
    

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

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

相关文章

Day56力扣打卡

打卡记录 数对统计&#xff08;DP状态压缩&#xff09; 参考文献 #include <bits/stdc.h>using namespace std;void solve(){int n;cin >> n;map<int, int> mapp;vector<int> a(n);for (auto& x : a){cin >> x;mapp[x] ;}vector<array&…

使用WebyogSQLyog使用数据库

数据库 实现数据持久化到本地&#xff1a; 使用完整的管理系统统一管理&#xff0c; 数据库&#xff08;DateBase&#xff09;&#xff1a; 为了方便数据存储和管理&#xff08;增删改查&#xff09;&#xff0c;将数据按照特定的规则存储起来 安装WebyogSQLyog -- 创建数…

101基于matlab的极限学习机ELM算法进行遥感图像分类

基于matlab的极限学习机ELM算法进行遥感图像分类&#xff0c;对所获取的遥感图片进行初步分类和最终分类。数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。

如何使用 Explain 分析 SQL 语句?

如何使用 Explain 分析 SQL 语句&#xff1f; MySQL中EXPLAIN命令是我们分析和优化SQL语句的利器。 如何使用EXPLAIN来分析SQL语句&#xff0c;接下来有15个例子&#xff0c;一起学习呗 1. EXPLAIN的基本使用 EXPLAIN可以用于分析MySQL如何执行一个SQL查询&#xff0c;包括如…

ElasticSearch之cat repositories API

命令样例如下&#xff1a; curl -X GET "https://localhost:9200/_cat/repositories?vtrue&pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; id type repo1 fs repo2 s3查…

python+gdal地理坐标转投影坐标

1 前言 地理坐标系&#xff0c;是使用三维球面来定义地球表面位置&#xff0c;以实现通过经纬度对地球表面点位引用的坐标系。 地理坐标系经过地图投影操作后就变成了投影坐标系。而地图投影是按照一定的数学法则将地球椭球面上点的经维度坐标转换到平面上的直角坐标。 2 流程…

基于STM32的四位数码管计数器设计与实现

✅作者简介&#xff1a;热爱科研的嵌入式开发者&#xff0c;修心和技术同步精进&#xff0c; 代码获取、问题探讨及文章转载可私信。 ☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。 &#x1f34e;获取更多嵌入式资料可点击链接进群领取&#xff0c;谢谢支持&#xff01;…

Docker Compose(容器编排)——9

目录 什么是 Docker Compose生活案例为什么要 Docker ComposeDocker Compose 的安装Docker Compose 的功能Docker Compose 使用场景Docker Compose 文件&#xff08;docker-compose.yml&#xff09; 文件语法版本文件基本结构及常见指令Docker Compose 命令清单 命令清单如下命…

垃圾回收器CMS和G1的区别

CMS和G1的区别 区别一&#xff1a; 使用范围不一样 CMS收集器是老年代的收集器&#xff0c;可以配合新生代的Serial和ParNew收集器一起使用 G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用 区别二&#xff1a; STW的时间 CMS收集器以最小的停顿时间为目标的收…

C++11(下)

可变参数模板 C11的新特性可变参数模板能够创建可以接受可变参数的函数模板和类模板. 相比C98/03, 类模版和函数模版中只能含固定数量的模版参数, 可变模版参数无疑是一个巨大的改进, 然而由于可变模版参数比较抽象, 使用起来需要一定的技巧, 所以这块还是比较晦涩的.掌握一些基…

Vue 3项目的运行过程

概述&#xff1a; 使用Vite构建Vue 3项目后&#xff0c;当执行yarn dev命令启动服务时&#xff0c;项目就会运行起来&#xff0c;该项目会通过src\main.js文件将src\App.vue组件渲染到index.html文件的指定区域。 文件介绍&#xff1a; src\App.vue文件 Vue 3项目是由各种组件…

递归实现指数型枚举

title: 递归实现指数型枚举 date: 2023-12-10 19:29:20 tags: 递归 catgories: 算法进阶指南 —> 传送门 题目大意 从 1 ~ n n n 这 n n n 个整数随机选取任意多个&#xff0c;输出所有可能的选择方案 思路 这等价于每个整数可以选或者不选&#xff0c;所有的方案总数共有…

Spring Boot的日志

打印日志 打印日志的步骤: • 在程序中得到日志对象. • 使用日志对象输出要打印的内容 在程序中得到日志对象 在程序中获取日志对象需要使用日志工厂LoggerFactory,代码如下: package com.example.demo;import org.slf4j.Logger; import org.slf4j.LoggerFactory;public c…

STM32——继电器

继电器工作原理 单片机供电 VCC GND 接单片机&#xff0c; VCC 需要接 3.3V &#xff0c; 5V 不行&#xff01; 最大负载电路交流 250V/10A &#xff0c;直流 30V/10A 引脚 IN 接收到 低电平 时&#xff0c;开关闭合。

Go Fyne 入门

Fyne是一个用于创建原生应用程序的UI工具包&#xff0c;它简单易用&#xff0c;并且支持跨平台。以下是一个简单的Fyne教程&#xff0c;帮助你入门&#xff1a; 1. 安装Fyne 首先&#xff0c;确保你已经安装了Go语言。然后&#xff0c;在终端中运行以下命令来安装Fyne&#x…

android-xml语法

xml解析器 Android的XML文件语法是由Android系统中的解析器解析的。具体来说&#xff0c;Android使用了一个名为"Android Asset Packaging Tool (AAPT)"的工具来解析和处理XML文件。AAPT负责将XML文件编译为二进制格式&#xff0c;并在构建过程中将其打包到Android应…

第2节:Vue3 模板语法

Vue3 的模板语法主要包括以下几个部分&#xff1a; 插值表达式&#xff1a;使用双大括号 {{ }} 包裹变量&#xff0c;可以直接在模板中显示变量的值。 <div>{{ message }}</div>指令&#xff1a;以 v- 开头&#xff0c;后面跟一个自定义的名字&#xff0c;用于操…

从Centos-7升级到Centos-Stream-8

如果在正式环境升级&#xff0c;请做好数据备份以及重要配置备份&#xff01;因为升级会造一部分应用被卸载。 注意&#xff1a;升级前请备份好数据&#xff0c;升级可能会导致ssh的root用户无法登陆、网卡名称发生改变、引导丢失无法开机等问题。 1.安装epel源 yum -y install…

【Spring教程20】Spring框架实战:AOP(面对切面编程)知识总结

欢迎大家回到《Java教程之Spring30天快速入门》&#xff0c;本教程所有示例均基于Maven实现&#xff0c;如果您对Maven还很陌生&#xff0c;请移步本人的博文《如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》&#xff0c;本文的上一篇为《利用 AOP通知获取数据代码…

软件测试(接口测试业务场景测试)

软件测试 手动测试 测试用例8大要素 编号用例名称&#xff08;标题&#xff09;模块优先级预制条件测试数据操作步骤预期结果 接口测试&#xff08;模拟http请求&#xff09; 接口用例设计 防止漏测方便分配工具&#xff0c;评估工作量和时间接口测试测试点 功能 单接口业…