当前位置: 首页 > news >正文

同步 异步

目录

1  什么是同步

1.1  定义

1.2  特点

1.3  示例

1.4  优点

1.5  缺点

2  什么是异步

2.1  定义

2.2  特点

2.3   示例

2.4  优点 

 2.5  缺点 

3  同步和异步的选择

3.1  什么时候使用同步:

3.2  什么时候使用异步:

4  举例对比

4.1  同步操作更好的场景

4.2  异步操作更好的场景

5  总结


1  什么是同步

1.1  定义

       同步操作是指在调用一个方法或函数时,调用者必须等待这个方法或函数执行完成之后,才能继续执行后续代码。换句话说,调用是阻塞的,直到操作完成为止。


1.2  特点

  • 调用者必须等待操作完成。
  • 操作是顺序执行的,只有当前操作完成后,程序才会继续执行下一个操作。

1.3  示例

         假设你要从数据库中获取一条数据并打印出来:

public void getDataAndPrint() {String data = getDataFromDatabase(); // 同步操作,必须等待数据获取完成System.out.println(data); // 获取到数据后才能执行这行代码
}

         在这个示例中,程序会等待 getDataFromDatabase() 完成(例如,数据库查询完成)后,才会继续执行 System.out.println(data)


1.4  优点

  • 代码逻辑简单,容易理解和调试。
  • 程序执行的顺序和操作的顺序一致,便于跟踪

1.5  缺点

  • 如果某个同步操作耗时较长,会导致整个程序的响应速度变慢,无法处理其他任务,容易出现“阻塞”现象。
  • 在处理 I/O 操作(如网络请求、文件读取)时,等待时间长可能会影响用户体验。

2  什么是异步

2.1  定义

       异步操作是指在调用一个方法或函数时,调用者不需要等待这个操作完成就可以继续执行后续代码。调用是非阻塞的,操作在后台执行,操作完成后通过回调或事件通知调用者。


2.2  特点

  • 调用者无需等待操作完成,操作在后台执行。
  • 操作完成后,结果会通过回调函数、事件通知或未来对象(如 FutureCompletableFuture)传递给调用者。

2.3   示例

        假设你要异步从数据库中获取数据并在获取完成后打印:

public void getDataAndPrintAsync() {CompletableFuture.supplyAsync(() -> getDataFromDatabase()) // 异步操作.thenAccept(data -> System.out.println(data)); // 数据获取完成后执行System.out.println("Continue executing other code"); // 不等待数据获取,继续执行
}

 在这个示例中,getDataFromDatabase() 在后台执行,System.out.println("Continue executing other code") 会立即执行,不需要等待数据库查询完成。当数据获取完成后,thenAccept 内的代码块才会执行。


2.4  优点 

  • 提高程序的响应速度:不需要等待耗时操作完成,程序可以继续执行其他任务。
  • 更好地利用系统资源,特别是在 I/O 操作密集型的应用中,异步处理可以显著提高系统的吞吐量和效率。

 2.5  缺点 

  • 代码逻辑复杂:异步代码通常涉及回调、事件处理或 Future 对象管理,理解和调试这些代码比同步代码困难。
  • 由于操作是在后台执行,容易出现竞态条件(race condition),需要额外的同步机制来保证线程安全。

3  同步和异步的选择

3.1  什么时候使用同步

  • 操作耗时较短,且不影响程序整体性能时。
  • 代码逻辑简单且不涉及大量 I/O 操作时。
  • 需要按照严格的顺序执行一系列操作时。

3.2  什么时候使用异步

  • 操作耗时较长,特别是涉及 I/O 操作(如网络请求、文件读取、数据库访问)时。
  • 需要并发处理多个任务,且希望在某些操作执行时继续处理其他任务时。
  • 希望提高系统的响应速度和资源利用率时,特别是在用户交互密集的应用中。

4  举例对比

4.1  同步操作更好的场景

        (1)场景:银行转账系统

        在银行的转账系统中,转账操作通常涉及到从一个账户中扣款并将资金转入另一个账户。这两个操作必须按照严格的顺序执行,并且在整个过程中不允许有任何中断或并发操作导致数据不一致。因此,在这种场景下,同步操作是更好的选择。

        (2)示例代码:

public class BankService {// 同步转账操作public synchronized void transfer(Account fromAccount, Account toAccount, double amount) {// 检查余额if (fromAccount.getBalance() >= amount) {// 从源账户扣款fromAccount.withdraw(amount);// 向目标账户存款toAccount.deposit(amount);System.out.println("转账成功:" + amount + " 从 " + fromAccount.getId() + " 到 " + toAccount.getId());} else {System.out.println("余额不足,转账失败。");}}
}class Account {private String id;private double balance;public Account(String id, double balance) {this.id = id;this.balance = balance;}public synchronized void withdraw(double amount) {balance -= amount;}public synchronized void deposit(double amount) {balance += amount;}public double getBalance() {return balance;}public String getId() {return id;}
}

         (3)分析

  • 同步操作的必要性:在转账过程中,如果操作不按顺序执行,可能会导致资金丢失或账户余额不一致的情况。因此,必须确保从账户中扣款和存入目标账户的操作是同步的。
  • 同步的优势:同步操作确保了数据的一致性和完整性,在关键的金融交易中非常重要。

4.2  异步操作更好的场景

        (1)场景:发送批量邮件

假设你管理一个电商平台,每当有新产品上架时,需要向成千上万的用户发送通知邮件。如果你采用同步操作,每次发送邮件都需要等待上一个邮件发送完成,这将导致整个过程耗时过长,且无法在邮件发送期间处理其他任务。在这种情况下,异步操作是更好的选择。

        (2)示例代码

import java.util.List;
import java.util.concurrent.CompletableFuture;public class EmailService {// 异步发送邮件操作public void sendBatchEmails(List<String> emailAddresses, String subject, String content) {for (String email : emailAddresses) {// 异步发送每封邮件CompletableFuture.runAsync(() -> sendEmail(email, subject, content));}System.out.println("批量邮件发送任务已启动,正在后台处理中...");}// 模拟邮件发送private void sendEmail(String email, String subject, String content) {try {// 模拟邮件发送的耗时操作Thread.sleep(1000);System.out.println("邮件已发送到:" + email);} catch (InterruptedException e) {e.printStackTrace();}}
}

         (3)分析

  • 异步操作的必要性:批量发送邮件的操作较耗时,尤其是在处理大量收件人时。采用异步操作可以在邮件发送的同时继续处理其他任务,例如响应用户请求或处理其他事务。
  • 异步的优势:异步操作不会阻塞主线程,能够显著提高系统的响应速度和吞吐量。在需要处理大量并发任务时,异步操作更为高效。

5  总结

  • 同步操作:简单、顺序执行,适合不涉及长时间等待的操作。
  • 异步操作:非阻塞、提高并发处理能力,适合长时间等待或需要并发处理的场景。

http://www.mrgr.cn/news/8878.html

相关文章:

  • Spire.PDF for .NET【文档操作】演示:创建 PDF 组合
  • SpringMVC核心机制环境搭建
  • 编织网络之魂:Ruby网络编程指南
  • rt-studio+clion+cubemx联合使用(使用scons进行整合)
  • Python高光谱遥感数据处理与机器学习深度应用
  • 华为OD题目 csv格式的数据 字符串 用C没写出来
  • 分布式数据一致性小结
  • 2002-2023年中债国债3年期到期收益率
  • Golang测试func TestXX(t *testing.T)的使用
  • 【机器学习】 1. 总览介绍
  • openai whisper使用
  • 在VBA中调用Adobe Acrobat或Reader的命令行工具,实现PDF自动打印 (‾◡◝)
  • Spring Boot日志
  • 排序算法【希尔排序】
  • Activity的启动流程(AndroidU)
  • 【互动直播】支付能力视角与年龄的调节作用—推文分享—2024-08-25
  • 手把手教你搭建 Go 项目
  • 考研资讯平台
  • 【数据结构-前缀异或和】1442. 形成两个异或相等数组的三元组数目
  • 华为Cloud连接配置